Emplibot – AI Content Writer with Keyword Research, Infographics, and Linking | SEO Optimized | Fully Automated <= 1.0.9 - Authenticated (Admin+) Server-Side Request Forgery
Description
The Emplibot – AI Content Writer with Keyword Research, Infographics, and Linking | SEO Optimized | Fully Automated plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 1.0.9 via the emplibot_call_webhook_with_error() and emplibot_process_zip_data() functions. This makes it possible for authenticated attackers, with Administrator-level access and above, to make web requests to arbitrary locations originating from the web application and can be used to query and modify information from internal services.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.0.9Source Code
WordPress.org SVNThis research plan focuses on CVE-2025-11970, an Authenticated (Admin+) SSRF in the Emplibot plugin. Since source files were not provided in the prompt, this plan is based on the vulnerability description and common WordPress plugin architectural patterns, with specific commands to locate the exact …
Show full research plan
This research plan focuses on CVE-2025-11970, an Authenticated (Admin+) SSRF in the Emplibot plugin. Since source files were not provided in the prompt, this plan is based on the vulnerability description and common WordPress plugin architectural patterns, with specific commands to locate the exact identifiers.
1. Vulnerability Summary
The Emplibot plugin (<= 1.0.9) contains a Server-Side Request Forgery (SSRF) vulnerability. The flaw exists within the emplibot_call_webhook_with_error() and emplibot_process_zip_data() functions. These functions likely accept a URL parameter from user input and use it in an HTTP request (via wp_remote_get or wp_remote_post) without sufficient validation. While restricted to Administrator-level users, this can be used to scan internal networks, access cloud metadata services (e.g., 169.254.169.254), or interact with internal services unreachable from the public internet.
2. Attack Vector Analysis
- Endpoint: Likely an AJAX handler (
admin-ajax.php) or an admin-side form submission handler (admin-post.phpor a settings page). - Vulnerable Functions:
emplibot_call_webhook_with_errorandemplibot_process_zip_data. - Action Name (Inferred): Likely
emplibot_call_webhookor similar. - Payload Parameter: Likely
url,webhook_url, orzip_url. - Authentication: Administrator level required.
- Preconditions: Plugin must be active. The attacker must have a valid administrator session.
3. Code Flow Analysis
To confirm the path, the agent should first locate the registration of these functions:
- Entry Point Discovery:
# Find where the functions are hooked grep -rnE "emplibot_call_webhook_with_error|emplibot_process_zip_data" /var/www/html/wp-content/plugins/emplibot/ - Hook Identification: Look for
add_action('wp_ajax_...', ...)oradd_action('admin_post_...', ...). - Sink Analysis: Inside the identified functions, look for the HTTP request sink:
wp_remote_get($url, ...)wp_remote_post($url, ...)wp_safe_remote_get(though if it's SSRF, it's likely the "safe" variant wasn't used or was bypassed).
- Trace:
- User sends POST request to
admin-ajax.phpwithaction=emplibot_some_actionandurl=http://internal-service. emplibot_some_actioncallback callsemplibot_call_webhook_with_error().- The URL is passed directly to a WordPress HTTP API function without host validation.
- User sends POST request to
4. Nonce Acquisition Strategy
Since this is an Admin+ vulnerability, a nonce is almost certainly required for the AJAX or POST request.
- Identify the Script/Page: Determine which admin page loads the Emplibot settings.
grep -rn "add_menu_page" /var/www/html/wp-content/plugins/emplibot/ - Locate Localization: Find the
wp_localize_scriptcall that exports the nonce.grep -rn "wp_localize_script" /var/www/html/wp-content/plugins/emplibot/ - Extraction (Step-by-Step):
- Navigate to the Emplibot settings page:
browser_navigate("http://localhost:8080/wp-admin/admin.php?page=emplibot-settings")(verify the slug viagrep). - Execute
browser_evalto find the nonce:// Example guess based on common naming conventions window.emplibot_obj?.nonce || window.emplibot_admin?.nonce - If not found via JS, check for hidden form fields:
document.querySelector('input[name="emplibot_nonce"]')?.value
- Navigate to the Emplibot settings page:
5. Exploitation Strategy
Once the endpoint and nonce are identified:
- Target:
http://localhost:8080/wp-admin/admin-ajax.php - Method: POST
- Headers:
Content-Type: application/x-www-form-urlencoded - Payload (emplibot_call_webhook_with_error path):
action=emplibot_call_webhook_with_error&url=http://169.254.169.254/latest/meta-data/&nonce=[EXTRACTED_NONCE] - Payload (emplibot_process_zip_data path):
action=emplibot_process_zip_data&zip_url=http://127.0.0.1:22/&nonce=[EXTRACTED_NONCE]
Tool Usage:
Use http_request via Playwright to send the request from the authenticated admin session.
6. Test Data Setup
- Plugin Installation: Ensure Emplibot <= 1.0.9 is installed and activated.
- User Creation: Create an admin user if one doesn't exist.
- Environment: If testing for internal port scanning, ensure a service is listening on a specific internal port (e.g., port 22 or a mock service).
7. Expected Results
- Successful SSRF: The response from the internal service (e.g., SSH banner or AWS metadata) is reflected in the plugin's AJAX response, OR a delay/difference in error message occurs indicating a connection was attempted.
- Verification: If the plugin logs errors, check if the "webhook error" log contains the content of the target URL.
8. Verification Steps
After the exploit attempt:
- Check Plugin Logs:
wp option get emplibot_logs # (Inferred option name) - Monitor Outbound Traffic: If possible, point the SSRF to a RequestBin-style listener or a local listener within the Docker network to confirm the request originated from the WP server.
9. Alternative Approaches
- Parameter Variation: If
urldoesn't work, trywebhook,zip, or checking theemplibot_process_zip_datafunction for how it handles the ZIP source. It might expect a JSON body or a specific file structure. - Gopher/Dict Protocols: If
curlis used internally instead ofwp_remote_get, attempt to usegopher://to interact with internal Redis/Memcached. - Bypass wp_safe_remote_get: If the plugin uses
wp_safe_remote_get, check if it can be bypassed using DNS rebinding or redirection if the plugin follows redirects.
Summary
The Emplibot plugin for WordPress (<= 1.0.9) is vulnerable to an authenticated Server-Side Request Forgery (SSRF) via the functions emplibot_call_webhook_with_error() and emplibot_process_zip_data(). This allows administrators to make arbitrary web requests from the server, potentially exposing internal services or cloud metadata.
Security Fix
@@ -... @@ - $response = wp_remote_post($url, $args); + $response = wp_safe_remote_post($url, $args); @@ -... @@ - $response = wp_remote_get($zip_url); + $response = wp_safe_remote_get($zip_url);
Exploit Outline
An authenticated administrator triggers the SSRF by sending a POST request to the WordPress AJAX endpoint (admin-ajax.php). The request must include the appropriate action parameter mapped to either 'emplibot_call_webhook_with_error' or 'emplibot_process_zip_data', along with a URL parameter ('url' or 'zip_url') pointing to a target internal service (e.g., http://169.254.169.254 for cloud metadata). A valid security nonce, which can be found in the plugin's settings page source, is required to authorize the request.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.