Affected plugin | Blackhole for Bad Bots |
Active installs | 30,000+ |
Vulnerable version | <= 3.3.3 |
Audited version | 3.3.3 |
Fully patched version | PENDING |
Recommended remediation | PENDING |
Description
A malicious bot spoofing his User-Agent header to one in the plugin’s allowlist can bypass the plugin’s full functionality.
Proof of concept
The HTTP_USER_AGENT header can not be trusted as an attacker / malicious bot can set it to arbitrary values.
The plugin uses the User-Agent header to decide if the current request should be exempt from offenses.
function blackhole_whitelist($vars) {
global $bbb_options;
list ($ip_address, $request_uri, $remote_host, $query_string, $user_agent, $referrer, $protocol, $method) = $vars;
// bots
$whitelist_bots = isset($bbb_options['bot_whitelist']) ? $bbb_options['bot_whitelist'] : '';
$whitelist_bots = array_filter(array_map('trim', explode(',', $whitelist_bots)));
if (!empty($whitelist_bots)) {
foreach ($whitelist_bots as $bot) {
if (stripos($user_agent, $bot) !== false) {
return true;
}
}
}
// ips
$whitelist_ips = isset($bbb_options['ip_whitelist']) ? $bbb_options['ip_whitelist'] : '';
$whitelist_ips = array_filter(array_map('trim', explode(',', $whitelist_ips)));
foreach ($whitelist_ips as $ip) {
if (strpos($ip, '/') === false) {
if (substr($ip_address, 0, strlen($ip)) === $ip) {
return true;
}
} else {
if (blackhole_ip_in_range($ip_address, $ip)) {
return true;
}
}
}
return false;
}
The User-Agent is determined in the blackhole_get_vars function.
$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field($_SERVER['HTTP_USER_AGENT']) : '';
The $user_agent variable is assigned directly from the untrusted HTTP header. Consequently, any bot that spoofs its User-Agent can bypass the plugin’s functionality.
curl -X GET https://local.test?blackhole=1 -H "User-Agent: google"
Proposed patch
Use PHP’s gethostbyaddr and gethostbyname functions to perform reverse DNS lookups if the value of the User-Agent header is in the allowlist.
See:
Timeline
Vendor contacted | September 13, 2022 |
First Response | September 13, 2022 |
Fully patched at | PENDING |
Publicly disclosed | April 24, 2023 |
Leave a Reply