What Is SSRF (Server-Side Request Forgery)?
SSRF is a security vulnerability that allows an attacker to trick your server into sending requests to internal services, localhost, or external systems. Instead of attacking directly from their own machine, the attacker uses your server as a proxy, often bypassing firewalls, WAFs, and access control rules.
The core issue behind SSRF is simple: the application allows a user to provide a URL, and the server fetches data from that URL without proper validation or restrictions.
Common Types of SSRF Attacks
The two most common forms of SSRF are:
- Basic SSRF: The server returns the response directly to the attacker. This can expose configs, credentials, internal admin pages, and more.
- Blind SSRF: The server sends the request but does not return the response. Attackers can still:
- Scan internal ports and services using timing differences or status codes.
- Access cloud metadata services (e.g.,
http://169.254.169.254/) to steal sensitive credentials.
In some cases, SSRF is not limited to HTTP. If supported, attackers may abuse schemes like file://, gopher://, or ftp:// to read files or communicate with other internal services.
Why Is SSRF Dangerous?
- Internal network access: Attackers can reach admin panels, database ports, or internal APIs.
- Cloud metadata access: Many cloud providers expose sensitive credentials via metadata endpoints.
- Firewall/WAF bypass: Requests come from your own server, making them appear trusted.
- Further exploitation: SSRF can lead to RCE, data exfiltration, or pivoting deeper into the infrastructure.
- DoS attacks: Attackers can abuse your server to flood another system or drain your resources.
How SSRF Happens in WordPress
WordPress frequently fetches external data: oEmbed, pingback, REST API calls, image previews, webhooks, and more. Combined with hundreds of plugins that accept user-provided URLs, SSRF vulnerabilities occur very often.
Common SSRF patterns in WP plugins/themes include:
- User-provided URLs passed directly into
wp_remote_get()orwp_safe_remote_get(). - Image proxy scripts using
?url=...without validation. - Webhook integrations that allow any custom endpoint URL.
- Preview or metadata extraction tools (oEmbed, link preview, etc.).
Example of a WordPress SSRF Vulnerability
<?php
add_action( 'init', function () {
if ( ! isset( $_GET['url'] ) ) {
return;
}
$url = $_GET['url']; // Vulnerable: user-controlled URL
$response = wp_remote_get( $url );
if ( is_wp_error( $response ) ) {
wp_die( 'Request error' );
}
echo wp_remote_retrieve_body( $response ); // Vulnerable: full response exposed
exit;
} );
Attack example:
https://example.com/wp-content/plugins/vulnerable-plugin/fetch.php?url=http://127.0.0.1:8080/admin
This exposes any internal admin page reachable from the server.
Real SSRF Cases in WordPress Core and Plugins
1. Pingback SSRF vulnerabilities
The WordPress pingback system has historically allowed SSRF because it sends requests to user-controlled URLs with inconsistent validation.
2. SSRF in popular plugins
- Plugins that take user-entered URLs and pass them directly into HTTP APIs.
- AJAX handlers without CSRF protection triggering internal requests.
- Plugins with customizable API endpoints (automation, AI, marketing, etc.).
3. wp_remote_get() vs wp_safe_remote_get()
wp_safe_remote_get() adds URL validation, but if your plugin still allows arbitrary URLs from users, SSRF can still happen.
How to Prevent SSRF in WordPress
1. Validate and sanitize URLs
- Allow only
httpandhttpsschemes. - Use
esc_url_raw(),filter_var(), andparse_url().
2. Implement a strict allowlist
$allowed_hosts = array(
'api.example.com',
'cdn.example.com',
);
$host = wp_parse_url( $url, PHP_URL_HOST );
if ( ! in_array( $host, $allowed_hosts, true ) ) {
return new WP_Error( 'forbidden_host', 'Host not allowed.' );
}
3. Do not return raw responses to the user
- Never echo full responses from external URLs.
- Extract only specific fields or sanitize content properly.
4. Handle redirects and DNS rebinding
- Disable or limit redirects.
- Revalidate each redirected URL.
- Resolve the IP and block private/loopback ranges.
5. Don’t rely solely on wp_safe_remote_get()
6. Harden server/network infrastructure
- Outbound firewall with “deny by default”.
- Network isolation for sensitive services.
- Monitor unusual outbound traffic.
7. For WordPress admins
- Keep WordPress, plugins, and themes updated.
- Disable pingback/XML-RPC if not needed.
Safe HTTP Wrapper Example for Developers
<?php
function myplugin_safe_http_get( $url, $args = array() ) {
$url = esc_url_raw( $url );
if ( ! $url || ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
return new WP_Error( 'invalid_url', 'Invalid URL.' );
}
$scheme = wp_parse_url( $url, PHP_URL_SCHEME );
if ( ! in_array( $scheme, array( 'http', 'https' ), true ) ) {
return new WP_Error( 'invalid_scheme', 'Scheme not allowed.' );
}
$allowed_hosts = array( 'api.example.com', 'cdn.example.com' );
$host = wp_parse_url( $url, PHP_URL_HOST );
if ( ! in_array( $host, $allowed_hosts, true ) ) {
return new WP_Error( 'forbidden_host', 'Host not allowed.' );
}
$default_args = array(
'timeout' => 5,
'redirection' => 0,
);
$response = wp_safe_remote_get( $url, wp_parse_args( $args, $default_args ) );
if ( is_wp_error( $response ) ) {
return $response;
}
return wp_remote_retrieve_body( $response );
}
Conclusion
SSRF is one of the most impactful vulnerabilities in WordPress. Any feature that accepts a URL must be treated as a high-risk component. Proper validation, allowlisting, and infrastructure hardening are essential to protect your website and prevent attackers from abusing your server.
Comments