How to partially block xmlrpc and allow necessary methods in WordPress

Contents

Overview — Why partially block xmlrpc.php and how this helps

WordPress exposes an XML-RPC endpoint at /xmlrpc.php that implements a set of remote methods (wp., pingback., blogger., system. and others). That endpoint is useful for legitimate clients (the official mobile apps historically, some remote publishing tools, some plugins such as Jetpack in older modes) but is frequently abused:

  • Pingback amplification attacks using pingback.ping and system.multicall to multiply requests and produce DDoS/amplification.
  • Brute-force login attempts using wp.getUsersBlogs or other wp. methods.
  • Unwanted attack surface for remote code paths that most sites do not need.

Completely disabling xmlrpc.php is simple but sometimes unacceptable because some valid clients or plugins still rely on a small set of xmlrpc methods. The best practice is to restrict xmlrpc.php to only the minimum set of methods you need, and to block known-abused methods (especially pingback. and system.multicall). This article gives several robust ways to do that: WordPress-level filtering, server-level rules (Nginx and Apache/mod_security), per-site IP-only rules, and test examples.

Strategy summary

  1. Identify which xmlrpc methods you need (mobile app? remote publishing? Jetpack?).
  2. At the WordPress level, remove or allow only the methods you require using the xmlrpc_methods filter.
  3. At the server level, block known-abused methods (pingback. and system.multicall) or implement a request-body inspection allowing only a whitelist of methods.
  4. Optionally, restrict access to /xmlrpc.php by IP if the remote client(s) have fixed IPs.
  5. Test thoroughly with curl and monitor logs.

1) WordPress-level restriction (recommended baseline)

WordPress exposes a filter named xmlrpc_methods. It provides a list (associative array) of method names to handler functions. You can use that filter to remove dangerous methods or to create a whitelist of allowed methods. Applying this filter is the most compatible approach because it runs inside WordPress and does not require server configuration.

Remove specific abused methods (quick, safe)

This example unsets the most problematic xmlrpc methods: pingback. and system.multicall. Place the code in a small mu-plugin (must-use plugin) or in a site-specific plugin avoid putting it in a themes functions.php so it survives theme changes.

lt?php
/
  mu-plugin or site plugin: block pingbacks and system.multicall
 /
add_filter(xmlrpc_methods, function(methods){
    // Remove pingback methods
    unset(methods[pingback.ping])
    unset(methods[pingback.extensions.getPingbacks])
    // Remove system.multicall to prevent method-batching amplification
    unset(methods[system.multicall])
    return methods
})

Whitelist-only approach (most restrictive)

If you know exactly which xmlrpc methods your site needs, build a whitelist. This removes every method except those listed. This is safest but you must include any method required by plugin(s) or external services you use.

lt?php
/
  mu-plugin: only allow a small set of xmlrpc methods
  Edit allowed_methods to include the keys you need.
 /
add_filter(xmlrpc_methods, function(methods){
    // Only these xmlrpc methods will remain (adjust as needed)
    allowed_methods = array(
        wp.getUsersBlogs,
        wp.getPosts,
        wp.getPost,
        wp.newPost,
        wp.editPost,
        wp.deletePost,
        wp.getCategories,
        wp.getTags,
        wp.newMediaObject,
        wp.getMediaLibrary,
        // add other wp. methods you require
    )

    // Intersect current methods with the allowed list
    methods = array_intersect_key(methods, array_flip(allowed_methods))
    return methods
})

Important notes about the WordPress-filter approach

  • It blocks by method name inside WordPress logic. This means the request still reaches PHP but WordPress will return an XML-RPC fault for disallowed methods.
  • It is fully compatible with WordPress authentication and capabilities checks already performed by the built-in handlers.
  • Because requests still hit PHP, attackers can still consume some CPU/IO, so pairing this with server-level blocking is advised for high-traffic attack situations.
  • If you use plugins that rely on xmlrpc (Jetpack, remote publishing tools), check their docs to identify required methods and add them to the allow list.

2) Server-level blocking — Nginx examples

Blocking at the web-server level is more efficient because it prevents PHP from being invoked. Nginx allows access to the request body via the request_body variable (it must read the body first). A common and effective approach is to inspect request_body and block specific methodName values or allow only a small whitelist.

Block pingback.ping and system.multicall (simple, common)

# inside your server block
location = /xmlrpc.php {
    # read client body for request_body usage
    client_body_buffer_size 128k

    # Block pingback.ping or system.multicall anywhere in the body
    if (request_body ~ pingback.ping) {
        return 403
    }
    if (request_body ~ system.multicall) {
        return 403
    }

    # Let PHP-FPM handle allowed requests
    include fastcgi_params
    fastcgi_pass unix:/var/run/php-fpm.sock
    fastcgi_param SCRIPT_FILENAME /path/to/wordpress/xmlrpc.php
}

Note: The regex uses case-insensitive matching (~). You can expand checks to block other method names. Nginx evaluates if statements sequentially returning 403 prevents PHP execution.

Whitelist xmlrpc methods at Nginx level (most restrictive)

This example allows only requests that contain one of the listed methodName entries all others are rejected. Adjust the allowed list to your needs.

location = /xmlrpc.php {
    client_body_buffer_size 128k

    # Allowed method names (pipe-separated)
    set xmlrpc_allowed 0
    if (request_body ~ (wp.getPostswp.newPostwp.getUsersBlogs)) {
        set xmlrpc_allowed 1
    }

    if (xmlrpc_allowed = 0) {
        return 403
    }

    include fastcgi_params
    fastcgi_pass unix:/var/run/php-fpm.sock
    fastcgi_param SCRIPT_FILENAME /path/to/wordpress/xmlrpc.php
}

Caveats:

  • Large request bodies and streaming clients may require adjusting buffer sizes test with real clients.
  • Some clients send methodName values with different whitespace/newlines — use tolerant regex patterns.

3) Server-level blocking — Apache and mod_security

Apaches mod_rewrite cannot inspect POST bodies. Use mod_security (WAF) to inspect the XML body and block or allow methods. If you dont run mod_security, consider using an Apache rule to restrict by IP instead (shown later).

mod_security rule to block pingback and system.multicall

# Example mod_security (SecRule) rule in your mod_security config
SecRule REQUEST_URI @endsWith /xmlrpc.php 
    phase:2,id:100001,log,deny,msg:Blocked xmlrpc pingback/multicall, 
    chain
    SecRule REQUEST_BODY @rx (pingback.pingsystem.multicall) 
    t:none

This rule denies any POST to /xmlrpc.php whose body contains pingback.ping or system.multicall. Expand the regex to detect additional method names you want to block.

4) .htaccess / Apache access restrictions (IP-based)

If only a small set of external IPs needs xmlrpc access (for example, a remote publishing system on static IPs), restrict xmlrpc.php to those IPs.

ltFiles xmlrpc.phpgt
    ltRequireAllgt
        Require all denied
        # Allow specific IPs or CIDR ranges
        Require ip 203.0.113.5
        Require ip 198.51.100.0/24
    lt/RequireAllgt
lt/Filesgt

This is extremely effective (prevents any access from unknown IPs), but only suitable when the legitimate clients use fixed IPs.

5) Returning a graceful XML-RPC fault from PHP for blocked methods

If you prefer requests to reach PHP but want an immediate XML-RPC fault for blocked methods, hook early and return a fault. This keeps logs inside PHP and is cleaner for remote clients that expect XML-RPC responses.

lt?php
/
  Return XML-RPC fault for disallowed methods early.
 /
add_filter(xmlrpc_methods, function(methods){
    // Let WordPress register its usual handlers,
    // well wrap the handler bodies using xmlrpc_call if needed.
    return methods
})

// Use this action to inspect the raw XML and die with a fault
add_action(xmlrpc_call, function(method){
    blocked = array(pingback.ping,system.multicall)
    if (in_array(method, blocked, true)) {
        xmlrpc_error(403, This XML-RPC method is disabled on this site.)
        exit
    }
}, 1)

Note: Some WordPress versions may not define xmlrpc_call in the same way prefer the xmlrpc_methods filter for compatibility. If using direct XML inspection, ensure the hook runs before handlers execute.

6) Practical testing and verification

Always test changes on staging before applying to production. Use curl to test allowed and blocked methods.

Example: XML-RPC call to wp.getUsersBlogs (test expected allowed)

curl -s -X POST https://example.com/xmlrpc.php 
  -H Content-Type: text/xml 
  -d 

  wp.getUsersBlogs
  
    username
    password
  

Example: XML-RPC pingback attempt (should be blocked)

curl -s -X POST https://example.com/xmlrpc.php 
  -H Content-Type: text/xml 
  -d 

  pingback.ping
  
    http://attacker.example/
    https://example.com/target-post/
  

# Expect a 403 (server-level block) or an XML-RPC fault response from WordPress.

7) Detecting usage and monitoring

Before you remove or block methods, check your server logs to see which xmlrpc methods are being called. Typical places:

  • Web server access logs (look for POST /xmlrpc.php requests).
  • mod_security logs (if enabled).
  • WordPress logs when running a plugin or mu-plugin that logs xmlrpc_method calls.

You can add temporary logging in a mu-plugin to record the xmlrpc method names and the calling IP, user agent and time before you block. Example:

lt?php
add_filter(xmlrpc_methods, function(methods){
    // Log method usage by wrapping handlers (simple approach)
    foreach (methods as name =gt handler) {
        orig = handler
        methods[name] = function() use (name, orig) {
            error_log(xmlrpc method called: {name} from  . _SERVER[REMOTE_ADDR])
            // Call original handler
            args = func_get_args()
            return call_user_func_array(orig, args)
        }
    }
    return methods
})

8) Additional recommendations and hardening tips

  • Disable Pingbacks in Settings: In WordPress Admin → Settings → Discussion, uncheck Allow link notifications from other blogs (pingbacks and trackbacks). This reduces some pingback activity at the WordPress level.
  • Pair WordPress and server-level controls: Use the xmlrpc_methods filter plus a server block (Nginx or mod_security) for best protection and efficiency.
  • Limit login attempts: Use rate-limiting for authentication attempts (fail2ban for log parsing or web-application firewall throttle rules).
  • Monitor for system.multicall: Because system.multicall multiplies attack impact, ensure it is blocked if you do not explicitly need batch calls.
  • Fallback plan: If legitimate functionality breaks, re-enable only the specific method(s) required and re-test.

9) Common method lists (for reference)

Typical WordPress xmlrpc methods:

  • wp. — methods for posting, editing, media, categories, tags, posts retrieval (wp.newPost, wp.editPost, wp.getPosts, wp.newMediaObject, etc.)
  • pingback.ping and pingback.extensions.getPingbacks — pingback protocol
  • system.listMethods, system.multicall — XML-RPC system methods
  • blogger. — Blogger API compatibility
  • mt. — MovableType compatibility

If you only use remote publishing or a mobile client, you most likely only need a handful of wp. methods and can safely remove the rest.

10) Troubleshooting

  1. If legitimate clients report 403 or method not found, inspect server logs and temporarily revert to a permissive configuration while you identify required methods.
  2. If Nginx request_body is empty, ensure the configuration does not stream bodies to a file only and client_body_buffer_size is adequate test with various clients.
  3. When using mod_security, watch the audit log to see which rule triggered and tune rules and regex accordingly.
  4. If you need further granularity (rate-limiting by IP for xmlrpc.php), add fail2ban rules or WAF throttling for that endpoint.

Appendix — Quick reference code snippets

Block pingback and system.multicall in PHP (copy-friendly)

lt?php
add_filter(xmlrpc_methods, function(methods){
    unset(methods[pingback.ping])
    unset(methods[pingback.extensions.getPingbacks])
    unset(methods[system.multicall])
    return methods
})

Nginx: block pingback and system.multicall

location = /xmlrpc.php {
    client_body_buffer_size 128k
    if (request_body ~ pingback.ping) { return 403 }
    if (request_body ~ system.multicall) { return 403 }
    include fastcgi_params
    fastcgi_pass unix:/var/run/php-fpm.sock
    fastcgi_param SCRIPT_FILENAME /path/to/wordpress/xmlrpc.php
}

Apache mod_security: block xmlrpc pingback/multicall

SecRule REQUEST_URI @endsWith /xmlrpc.php phase:2,id:100001,log,deny,msg:Blocked xmlrpc pingback/multicall,chain
SecRule REQUEST_BODY @rx (pingback.pingsystem.multicall) t:none

Final notes

Partially blocking xmlrpc.php while allowing only necessary methods gives you a good balance between compatibility and security. Start by identifying which xmlrpc methods you actually need, implement a WordPress-level whitelist or method removal, and then harden the endpoint at the web-server/WAF level to avoid unnecessary PHP processing. Test carefully and monitor logs after deploying changes.



Acepto donaciones de BAT's mediante el navegador Brave 🙂



Leave a Reply

Your email address will not be published. Required fields are marked *