WordPress SSRF: Internal Network Scanning Via Health Check Plugin
Server-Side Request Forgery (SSRF) vulnerabilities pose a significant threat to web applications, potentially allowing attackers to compromise internal networks. This article delves into an authenticated SSRF vulnerability discovered in the WordPress Health Check & Troubleshooting plugin (up to version 1.7.1). We'll explore how this vulnerability can be exploited to perform internal network scanning, the impact it can have, and how to mitigate the risk.
The Heart of the Matter: Authenticated SSRF
At the core of this vulnerability lies the can_perform_loopback() function within the HealthCheck/class-health-check-loopback.php file. This function is triggered by various AJAX actions on the Site Health page. This function constructs a request URL using the admin_url() WordPress function. The admin_url() function is designed to generate URLs within the WordPress admin interface. However, its return value is directly influenced by the "Site Address (URL)" setting in WordPress's general settings. An attacker, having administrator privileges, can modify the "Site Address (URL)" to an internal IP address of their choosing. The plugin then uses this modified URL in a wp_remote_get() request without proper validation or whitelisting. This oversight allows attackers to trick the server into sending requests to internal resources, potentially revealing sensitive information or enabling further attacks. The essence of the exploit relies on the plugin’s trust in the admin_url() output and its lack of input validation before making requests.
The Impact of the Vulnerability
The implications of this vulnerability are severe. An attacker could potentially: discover live hosts on the internal network, perform port scanning to identify open ports, and discover internal services running on those ports (like internal admin panels, databases, or APIs). This information provides a critical foothold for an attacker, allowing them to pivot and launch further attacks against potentially vulnerable internal systems. The ability to scan the internal network allows for a comprehensive mapping of the internal infrastructure, including identifying services and hosts that might otherwise be hidden behind a firewall. Armed with this knowledge, attackers can launch targeted attacks, exploiting vulnerabilities in internal applications or services and ultimately gaining unauthorized access to sensitive data and systems. The vulnerability can lead to sensitive information disclosure about the internal network topology.
Step-by-Step Exploitation: A Practical Guide
To understand the vulnerability, let’s walk through the steps to reproduce the exploit. This PoC was successfully reproduced on a standard WordPress 6.8.2 installation with the Health Check & Troubleshooting plugin version 1.7.1. Make sure to only perform these actions on a testing environment you control.
1. Setting Up the Stage: Environment Preparation
- First, start with a clean WordPress installation. For this demonstration, let's assume it’s accessible at
http://wp.test. - Log in to the WordPress admin panel as an administrator.
- Install and activate the
Health Check & Troubleshootingplugin. You can find it by navigating to "Plugins" -> "Add New" and searching for it in the WordPress repository.
2. Establishing Baseline Behavior
- Use your browser's developer tools. Log in as the administrator and navigate to "Tools" -> "Site Health". Open the Developer Tools (
F12), then switch to the "Network" tab. - Observe the normal AJAX requests. Refresh the Site Health page and note the response times, which should be fast (e.g., under 1 second).
3. Attack Step 1: Identifying a Non-Existent Host
- Modify the Site Address. As the administrator, go to "Settings" -> "General".
- Set the "Site Address (URL)" to a non-existent IP address on your internal network (e.g.,
http://192.168.6.99). Adjust this IP to one that doesn't exist on your network for testing purposes. - Save the changes.
- Trigger the SSRF. Navigate to "Tools" -> "Site Health".
- Observe the Timeout. In the "Network" tab, observe the
site-healthrelated XHR requests and notice that the requests take a very long time, matching the cURL timeout (approximately 10-11 seconds).
4. Attack Step 2: Discovering a Live Internal Host
- Identify the Router's IP Address. Find your router's IP address. Use
ipconfigorip afor this (e.g.,192.168.6.2). - Modify the Site Address. As the administrator, go back to "Settings" -> "General".
- Set the "Site Address (URL)" to your router's IP address:
http://192.168.6.2. - Save the changes.
- Trigger the SSRF. Go back to "Tools" -> "Site Health".
- Observe the Immediate Response. In the "Network" tab, observe that the
site-healthrelated XHR requests now complete almost instantly (e.g., under 1 second).
5. Attack Step 3: Direct Request Forgery
- Start a Local Listening Server. On your local machine, run
python -m http.server 8888to start a simple HTTP server. - Modify the Site Address. Go to "Settings" -> "General". Set the "Site Address (URL)" to your local machine's IP address and a port, along with a unique path (e.g.,
http://192.168.6.146:8888/ssrf_proof). Replace192.168.6.146with your machine’s actual IP address. - Save the changes and Trigger the SSRF. Navigate to "Tools" -> "Site Health".
- Observe the Direct Hit. Check your Python server's console for incoming
GETrequests from the WordPress server, confirming the SSRF.
Recommendations for Remediation
To mitigate this vulnerability, the can_perform_loopback() function in HealthCheck/class-health-check-loopback.php must not blindly trust the output of admin_url(). A robust validation and whitelisting mechanism is crucial before the URL is passed to wp_remote_get(). This check should ensure that the hostname of the target URL resolves to a public IP address or, if resolving to a private IP, matches the server's own known IP addresses. WordPress core functions like wp_http_validate_url() can serve as a reference for a secure implementation.
Conclusion: Securing Your WordPress Site
This SSRF vulnerability highlights the importance of input validation and secure coding practices. By exploiting this vulnerability, an attacker can gain significant control over your internal network. Implementing the recommended mitigations is crucial to protect your WordPress site and prevent potentially devastating attacks. Regularly updating your plugins and themes is vital to stay ahead of these types of threats. The ability to modify the