WordPress Security

Protecting WordPress XML-RPC: Security Risks and Solutions

Understand XML-RPC security risks in WordPress and learn how to protect or disable this protocol to prevent brute force and DDoS attacks.

S
Sarah Chen
8 min read
2,001 views
Understanding and protecting WordPress XML-RPC protocol

XML-RPC is a remote procedure call protocol that allows external applications to communicate with WordPress. While useful for some applications, it presents significant security risks if left unprotected.

What is XML-RPC?

XML-RPC enables remote publishing through:

  • WordPress mobile apps
  • Jetpack plugin connectivity
  • Remote posting applications
  • Pingbacks and trackbacks
  • Desktop blogging clients

Security Risks

XML-RPC vulnerabilities include:

  • Brute force amplification attacks
  • DDoS through pingback abuse
  • Credential harvesting attempts
  • System information disclosure

Brute Force Amplification

XML-RPC allows testing multiple passwords in one request:

// Attacker can test 500 passwords in single request
// via system.multicall method
// This bypasses traditional brute force protection

Completely Disabling XML-RPC

If you do not need XML-RPC functionality:

// Disable XML-RPC completely
add_filter('xmlrpc_enabled', '__return_false');

// Also remove XML-RPC link from header
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wlwmanifest_link');

// Block access via .htaccess
// Add to WordPress root .htaccess:
// 
//     Order Deny,Allow
//     Deny from all
// 

Selective Method Blocking

Block dangerous methods while keeping useful ones:

// Block specific XML-RPC methods
add_filter('xmlrpc_methods', function($methods) {
    // Block pingbacks (DDoS vector)
    unset($methods['pingback.ping']);
    unset($methods['pingback.extensions.getPingbacks']);

    // Block credential testing methods
    unset($methods['system.multicall']);
    unset($methods['system.listMethods']);
    unset($methods['system.getCapabilities']);

    // Block user enumeration
    unset($methods['wp.getUsers']);
    unset($methods['wp.getAuthors']);

    return $methods;
});

Rate Limiting XML-RPC

Implement request throttling:

function rate_limit_xmlrpc() {
    if (strpos($_SERVER['REQUEST_URI'], 'xmlrpc.php') === false) {
        return;
    }

    $ip = $_SERVER['REMOTE_ADDR'];
    $key = 'xmlrpc_requests_' . md5($ip);
    $requests = get_transient($key) ?: 0;

    // Allow only 5 XML-RPC requests per minute
    if ($requests > 5) {
        header('HTTP/1.1 429 Too Many Requests');
        header('Retry-After: 60');
        exit('Rate limit exceeded');
    }

    set_transient($key, $requests + 1, MINUTE_IN_SECONDS);
}
add_action('init', 'rate_limit_xmlrpc', 1);

Authentication Enhancement

Require stronger authentication for XML-RPC:

// Require application passwords for XML-RPC
add_filter('xmlrpc_enabled', function($enabled) {
    if (!isset($_SERVER['PHP_AUTH_USER'])) {
        return false;
    }

    $user = wp_authenticate($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);

    if (is_wp_error($user)) {
        return false;
    }

    // Log XML-RPC authentication
    error_log(sprintf(
        'XML-RPC auth: User %s from IP %s',
        $user->user_login,
        $_SERVER['REMOTE_ADDR']
    ));

    return $enabled;
});

IP Whitelisting

Allow XML-RPC only from trusted IPs:

function whitelist_xmlrpc_ips() {
    if (strpos($_SERVER['REQUEST_URI'], 'xmlrpc.php') === false) {
        return;
    }

    $allowed_ips = array(
        '192.168.1.100',    // Office IP
        '10.0.0.0/8',       // Internal network
        '203.0.113.50',     // Automation server
    );

    $client_ip = $_SERVER['REMOTE_ADDR'];
    $allowed = false;

    foreach ($allowed_ips as $ip) {
        if (strpos($ip, '/') !== false) {
            // CIDR notation
            if (cidr_match($client_ip, $ip)) {
                $allowed = true;
                break;
            }
        } else {
            if ($client_ip === $ip) {
                $allowed = true;
                break;
            }
        }
    }

    if (!$allowed) {
        header('HTTP/1.1 403 Forbidden');
        exit('Access denied');
    }
}
add_action('init', 'whitelist_xmlrpc_ips', 1);

Monitoring XML-RPC Activity

Track and alert on suspicious activity:

function monitor_xmlrpc_activity() {
    if (strpos($_SERVER['REQUEST_URI'], 'xmlrpc.php') === false) {
        return;
    }

    $log_entry = array(
        'time' => current_time('mysql'),
        'ip' => $_SERVER['REMOTE_ADDR'],
        'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown',
        'method' => $_SERVER['REQUEST_METHOD'],
    );

    // Get request body for method detection
    $body = file_get_contents('php://input');
    if (preg_match('/([^<]+)<\/methodName>/', $body, $matches)) {
        $log_entry['xmlrpc_method'] = $matches[1];
    }

    // Check for multicall (brute force indicator)
    if (isset($log_entry['xmlrpc_method']) && $log_entry['xmlrpc_method'] === 'system.multicall') {
        wp_mail(
            get_option('admin_email'),
            'XML-RPC Brute Force Attempt',
            sprintf(
                'Multicall request detected from IP: %s',
                $log_entry['ip']
            )
        );
    }

    $logs = get_option('xmlrpc_access_log', array());
    array_unshift($logs, $log_entry);
    $logs = array_slice($logs, 0, 500);
    update_option('xmlrpc_access_log', $logs);
}
add_action('init', 'monitor_xmlrpc_activity', 0);

Jetpack Compatibility

Keep XML-RPC for Jetpack while blocking attacks:

function jetpack_xmlrpc_filter($enabled) {
    // Allow Jetpack IP ranges
    $jetpack_ips = array(
        '122.248.245.244',
        '54.217.201.243',
        '54.232.116.4',
        // Add current Jetpack IPs from their documentation
    );

    $client_ip = $_SERVER['REMOTE_ADDR'];

    // Allow if from Jetpack
    if (in_array($client_ip, $jetpack_ips)) {
        return true;
    }

    // Check for Jetpack user agent
    $ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
    if (strpos($ua, 'Jetpack') !== false) {
        return true;
    }

    // Block all other XML-RPC
    return false;
}
add_filter('xmlrpc_enabled', 'jetpack_xmlrpc_filter');

Server-Level Block

Block XML-RPC at the server level for best performance:

# Apache .htaccess
<Files xmlrpc.php>
    <RequireAll>
        Require ip 192.168.1.0/24
        Require ip 10.0.0.0/8
    </RequireAll>
</Files>

# Nginx configuration
location = /xmlrpc.php {
    allow 192.168.1.0/24;
    allow 10.0.0.0/8;
    deny all;
}

Conclusion

Unless you specifically need XML-RPC for mobile apps or remote publishing, disable it completely. If required, implement strict IP whitelisting, rate limiting, and monitoring to minimize attack surface.

Share:
S
Written by Sarah Chen

WP Folder Shield Team

Related Articles

SEO Spam Injection: How to Detect Hidden Links and Malicious Redirects
SEO Spam Injection: How to Detect Hidden Links and Malicious Redirects

Learn how hackers inject hidden links and malicious redirects into WordPress sites to steal your...

January 18, 2026
Understanding WordPress Malware Signatures and Detection Patterns
Understanding WordPress Malware Signatures and Detection Patterns

Learn how malware scanners detect threats using signatures and patterns. Understand the technology...

January 15, 2026
Country Blocking for WooCommerce: Protect Your Online Store
Country Blocking for WooCommerce: Protect Your Online Store

Learn how to implement country blocking for WooCommerce stores. Prevent fraud, reduce chargebacks...

January 10, 2026

Ready to Secure Your WordPress Site?

Get complete protection with WP Folder Shield.

Get Started