DOS through IP spoofing – (WordFence <= 7.6.2)

| in


Affected pluginWordFence
Active installs4+ million
Vulnerable version<= 7.6.2
Audited version7.6.1
Fully patched version
Recommended remediationEnsure that nobody can bypass your site’s reverse proxy and connect directly to the server. Use something like Cloudflare’s authenticated origin pulls.

Description


The plugin is vulnerable to IP spoofing if the target site is behind a reverse proxy and if WordFence is configured to fetch the IP address from any source besides REMOTE_ADDR (the default).
An attacker can exploit this to ban legitimate users, search-engine crawlers, or the site’s reverse proxy.

Proof of concept


WordFence handles IP detection better than most WordPress plugins.
However, the plugin is vulnerable to IP spoofing if a site is behind a reverse proxy and if the attacker can directly connect to the target server where WordFence runs.

This advanced attack scenario is described here.

The most common scenario for this attack is the following:

Most WordPress hosts that offer integrations with popular reverse proxies like Cloudflare do not configure the server to only be accessible through the reverse proxy.
In most cases, the only thing preventing an attacker from directly connecting to the server is uncovering its IP address. Often, this is easier than it should be using automated pentesting tools like theHarvester

Suppose WordFence is configured to get the IP address from the “X-Forwarded-For” header (XFF).

To verify that IP spoofing is possible, create the following must-use plugin on a local WordPress installation where WordFence is installed.

<?php

declare(strict_types=1);

// This code runs before WordFence.
// There should be no difference between running this code and a reverse proxy. WF should not be able to tell
// the difference.

define('REAL_USER_IP', '157.29.91.106'); // Hardcode the real user ip.


/*
 * Simulates a direct connection where all headers are passed as is.
 *
 * There might be web server configurations that drop any extra
 * headers such as X-Forwarded-For. But we can't know that
 * nor rely on it.
 */
$_SERVER['REMOTE_ADDR'] = REAL_USER_IP;

if (isset($_SERVER['HTTP_X_TEST'])) {
    add_action('wp_loaded', function () {
        $ip = wfUtils::getIP();
        echo "$ip\n";
        die();
    });
}
curl -X GET  https://local.test -H "X-Forwarded-For: 147.93.33.75" -H "X-TEST: 1"
147.93.33.75 # IP spoofed

The entire WordFence plugin is now using a spoofed IP which an attacker can use to:

  • Bypass the WordFence WAF
  • Bypass 2FA requirements
  • Bypass country blocking
  • Getting search-engine crawlers banned and thus potentially getting the target site delisted
  • Ban the site’s reverse proxy

Proposed patch


The needed patch is described in great length in this article of us.

Summary: Only ever use REMOTE_ADDR to access to current IP.

However, if WordFence wants to keep using a PHP implementation to detect the IP, it needs to have some mechanism to prevent reading IP addresses from HTTP headers if the connecting IP is not from a trusted proxy.

A sample implementation might look light this (pseudo code):

function verifyConnectingIPisTrustedProxy(array $trusted_proxies, string $connection_ip) :void {
    
    foreach ($trusted_proxies as $proxies) {
        
        $trusted = /* Check if $connection_ip is in subnet */
        
        if($trusted){
            return;
        }
        
    }
    // Educate the users about why this happened. Probably their web host already did the conversion to REMOTE_ADDR, or an attacker can directly connect to the server
    return throw BrokenConfigurationException();
  
}

Timeline


Vendor contactedSeptember 08, 2022
First ResponseSeptember 08, 2022
Fully patched at
Publicly disclosedApril 24, 2023

Miscellaneous


  • The vendor did not consider this a security vulnerability that needs immediate attention or patches.

Leave a Reply

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