/** * Determines whether a given IP address is whitelisted * * @param string $ip_to_check ip to check * @param array $white_ips ip list to compare to if not yet saved to options * @param boolean $current whether to whitelist the current ip or not (due to saving, etc) * * @return boolean true if whitelisted or false */ public static function is_ip_whitelisted($ip_to_check, $white_ips = null, $current = false) { $ip_to_check = trim($ip_to_check); if ($white_ips === null) { $global_settings = get_site_option('itsec_global'); $white_ips = isset($global_settings['lockout_white_list']) ? $global_settings['lockout_white_list'] : array(); } if ($current === true) { $white_ips[] = ITSEC_Lib::get_ip(); //add current user ip to whitelist to check automatically } foreach ($white_ips as $white_ip) { $converted_white_ip = ITSEC_Lib::ip_wild_to_mask($white_ip); $check_range = ITSEC_Lib::cidr_to_range($converted_white_ip); $ip_range = ITSEC_Lib::cidr_to_range($ip_to_check); if (sizeof($check_range) === 2) { //range to check $check_min = ip2long($check_range[0]); $check_max = ip2long($check_range[1]); if (sizeof($ip_range) === 2) { $ip_min = ip2long($ip_range[0]); $ip_max = ip2long($ip_range[1]); /** * Checks cover the following scenarios: * - min-a, min-b, max-a, max-b : min-b is in a range and min-a is in b range * - min-b, min-a, max-b, max-a : max-b is in a range and max-a is in b range * - min-a, min-b, max-b, max-a : range b is encapsulated by range a * - min-b, min-a, max-a, max-b : range a is encapsulated by range b */ if ($check_min <= $ip_min && $ip_min <= $check_max || $check_min <= $ip_max && $ip_max <= $check_max || $ip_min <= $check_min && $check_min <= $ip_max || $ip_min <= $check_max && $check_max <= $ip_max) { return true; } } else { $ip = ip2long($ip_range[0]); if ($check_min <= $ip && $ip <= $check_max) { return true; } } } else { //single ip to check $check = ip2long($check_range[0]); if (sizeof($ip_range) === 2) { $ip_min = ip2long($ip_range[0]); $ip_max = ip2long($ip_range[1]); if ($ip_min <= $check && $check <= $ip_max) { return true; } } else { $ip = ip2long($ip_range[0]); if ($check == $ip) { return true; } } } } return false; }
/** * Determines whether a given IP address is whitelisted * * @param string $ip_to_check ip to check * @param array $white_ips ip list to compare to if not yet saved to options * @param boolean $current whether to whitelist the current ip or not (due to saving, etc) * * @return boolean true if whitelisted or false */ public static function is_ip_whitelisted($ip_to_check, $white_ips = null, $current = false) { $ip_to_check = trim($ip_to_check); if ($white_ips === null) { $global_settings = get_site_option('itsec_global'); $white_ips = isset($global_settings['lockout_white_list']) ? $global_settings['lockout_white_list'] : array(); } if ($current === true) { $white_ips[] = ITSEC_Lib::get_ip(); //add current user ip to whitelist to check automatically } foreach ($white_ips as $white_ip) { $converted_white_ip = ITSEC_Lib::ip_wild_to_mask($white_ip); $check_range = ITSEC_Lib::cidr_to_range($converted_white_ip); $ip_range = ITSEC_Lib::cidr_to_range($ip_to_check); if (sizeof($check_range) === 2) { //range to check $check_min = ip2long($check_range[0]); $check_max = ip2long($check_range[1]); if (sizeof($ip_range) === 2) { $ip_min = ip2long($ip_range[0]); $ip_max = ip2long($ip_range[1]); if ($check_min < $ip_min && $ip_min < $check_max || $check_min < $ip_max && $ip_max < $check_max) { return true; } } else { $ip = ip2long($ip_range[0]); if ($check_min < $ip && $ip < $check_max) { return true; } } } else { //single ip to check $check = ip2long($check_range[0]); if (sizeof($ip_range) === 2) { $ip_min = ip2long($ip_range[0]); $ip_max = ip2long($ip_range[1]); if ($ip_min < $check && $check < $ip_max) { return true; } } else { $ip = ip2long($ip_range[0]); if ($check == $ip) { return true; } } } } return false; }
/** * Determines whether a given IP address is whitelisted. * * @since 4.0 * * @access private * * @param string $ip_to_check ip to check * * @return boolean true if whitelisted or false */ private function is_ip_whitelisted($ip_to_check, $current = false) { global $itsec_globals; $white_ips = $itsec_globals['settings']['lockout_white_list']; if (!is_array($white_ips)) { $white_ips = explode(PHP_EOL, $white_ips); } //Add the server IP address if (isset($_SERVER['LOCAL_ADDR'])) { $white_ips[] = $_SERVER['LOCAL_ADDR']; } elseif (isset($_SERVER['SERVER_ADDR'])) { $white_ips[] = $_SERVER['SERVER_ADDR']; } if ($current === true) { $white_ips[] = ITSEC_Lib::get_ip(); //add current user ip to whitelist to check automatically } $temp = get_site_option('itsec_temp_whitelist_ip'); if ($temp !== false) { if ($temp['exp'] < $itsec_globals['current_time']) { delete_site_option('itsec_temp_whitelist_ip'); } else { $white_ips[] = filter_var($temp['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); } } if (is_array($white_ips) && sizeof($white_ips > 0)) { foreach ($white_ips as $white_ip) { $converted_white_ip = ITSEC_Lib::ip_wild_to_mask($white_ip); $check_range = ITSEC_Lib::cidr_to_range($converted_white_ip); $ip_range = ITSEC_Lib::cidr_to_range($ip_to_check); if (sizeof($check_range) === 2) { //range to check $check_min = ip2long($check_range[0]); $check_max = ip2long($check_range[1]); if (sizeof($ip_range) === 2) { $ip_min = ip2long($ip_range[0]); $ip_max = ip2long($ip_range[1]); if ($check_min < $ip_min && $ip_min < $check_max || $check_min < $ip_max && $ip_max < $check_max) { return true; } } else { $ip = ip2long($ip_range[0]); if ($check_min < $ip && $ip < $check_max) { return true; } } } else { //single ip to check $check = ip2long($check_range[0]); if (sizeof($ip_range) === 2) { $ip_min = ip2long($ip_range[0]); $ip_max = ip2long($ip_range[1]); if ($ip_min < $check && $check < $ip_max) { return true; } } else { $ip = ip2long($ip_range[0]); if ($check == $ip) { return true; } } } } } return false; }
protected function get_server_config_ban_hosts_rules($server_type) { if (true !== $this->settings['enabled']) { return ''; } if (!is_array($this->settings['host_list']) || empty($this->settings['host_list'])) { return ''; } if (!class_exists('ITSEC_Ban_Users')) { require dirname(__FILE__) . '/class-itsec-ban-users.php'; } $host_rules = ''; $set_env_rules = ''; $deny_rules = ''; $require_rules = ''; // process hosts list foreach ($this->settings['host_list'] as $host) { $host = ITSEC_Lib::ip_wild_to_mask($host); $host = trim($host); if (empty($host)) { continue; } if (ITSEC_Ban_Users::is_ip_whitelisted($host)) { /** * @todo warn the user the ip to be banned is whitelisted */ continue; } if (in_array($server_type, array('apache', 'litespeed'))) { $converted_host = ITSEC_Lib::ip_mask_to_range($host); $converted_host = trim($converted_host); if (empty($converted_host)) { continue; } $set_env_host = str_replace('.', '\\.', $converted_host); $set_env_rules .= "\tSetEnvIF REMOTE_ADDR \"^{$set_env_host}\$\" DenyAccess\n"; // Ban IP $set_env_rules .= "\tSetEnvIF X-FORWARDED-FOR \"^{$set_env_host}\$\" DenyAccess\n"; // Ban IP from a proxy $set_env_rules .= "\tSetEnvIF X-CLUSTER-CLIENT-IP \"^{$set_env_host}\$\" DenyAccess\n"; // Ban IP from a load balancer $set_env_rules .= "\n"; $require_host = str_replace('.[0-9]+', '', $converted_host); $require_rules .= "\t\t\tRequire not ip {$require_host}\n"; $deny_rules .= "\t\tDeny from {$require_host}\n"; } else { if ('nginx' === $server_type) { $host_rules .= "\tdeny {$host};\n"; } } } $rules = ''; if ('apache' === $server_type) { if (!empty($set_env_rules)) { $rules .= "\n"; $rules .= "\t# " . __('Ban Hosts - Security > Settings > Banned Users', 'better-wp-security') . "\n"; $rules .= $set_env_rules; $rules .= "\t<IfModule mod_authz_core.c>\n"; $rules .= "\t\t<RequireAll>\n"; $rules .= "\t\t\tRequire all granted\n"; $rules .= "\t\t\tRequire not env DenyAccess\n"; $rules .= $require_rules; $rules .= "\t\t</RequireAll>\n"; $rules .= "\t</IfModule>\n"; $rules .= "\t<IfModule !mod_authz_core.c>\n"; $rules .= "\t\tOrder allow,deny\n"; $rules .= "\t\tAllow from all\n"; $rules .= "\t\tDeny from env=DenyAccess\n"; $rules .= $deny_rules; $rules .= "\t</IfModule>\n"; } } else { if ('litespeed' === $server_type) { if (!empty($set_env_rules)) { $rules .= "\n"; $rules .= "\t# " . __('Ban Hosts - Security > Settings > Banned Users', 'better-wp-security') . "\n"; $rules .= $set_env_rules; $rules .= "\t<IfModule mod_litespeed.c>\n"; $rules .= "\t\tOrder allow,deny\n"; $rules .= "\t\tAllow from all\n"; $rules .= "\t\tDeny from env=DenyAccess\n"; $rules .= $deny_rules; $rules .= "\t</IfModule>\n"; } } else { if ('nginx' === $server_type) { if (!empty($host_rules)) { $rules .= "\n"; $rules .= "# " . __('Ban Hosts - Security > Settings > Banned Users', 'better-wp-security') . "\n"; $rules .= $host_rules; } } } } return $rules; }
/** * Build the rewrite rules and sends them to the file writer * * @param array $input array of options, ips, etc * @param boolean $current whether the current IP can be included in the ban list * * @return array array of rules to send to file writer */ public static function build_rewrite_rules($input = null, $current = false) { //setup data structures to write. These are simply lists of all IPs and hosts as well as options to check if ($input === null) { //blocking ip on the fly $input = get_site_option('itsec_ban_users'); } $default = $input['default']; $enabled = $input['enabled']; $raw_host_list = $input['host_list']; $raw_agent_list = $input['agent_list']; $server_type = ITSEC_Lib::get_server(); //Get the server type to build the right rules //initialize lists so we can check later if we've used them $host_list = ''; $agent_list = ''; $default_list = ''; $host_rule2 = ''; //load the default blacklist if needed if ($default === true && $server_type === 'nginx') { $default_list = file_get_contents(plugin_dir_path(__FILE__) . 'lists/hackrepair-nginx.inc'); } elseif ($default === true) { $default_list = file_get_contents(plugin_dir_path(__FILE__) . 'lists/hackrepair-apache.inc'); } //Only process other lists if the feature has been enabled if ($enabled === true) { //process hosts list if (is_array($raw_host_list)) { foreach ($raw_host_list as $host) { $host = ITSEC_Lib::ip_wild_to_mask($host); if (!class_exists('ITSEC_Ban_Users')) { require dirname(__FILE__) . '/class-itsec-ban-users.php'; } if (!ITSEC_Ban_Users::is_ip_whitelisted($host, null, $current)) { $converted_host = ITSEC_Lib::ip_mask_to_range($host); if (strlen(trim($converted_host)) > 1) { if ($server_type === 'nginx') { //NGINX rules $host_rule = "\tdeny " . trim($host) . ';'; } else { //rules for all other servers $dhost = str_replace('.', '\\.', trim($converted_host)); //re-define $dhost to match required output for SetEnvIf-RegEX $host_rule = "SetEnvIF REMOTE_ADDR \"^" . $dhost . "\$\" DenyAccess" . PHP_EOL; //Ban IP $host_rule .= "SetEnvIF X-FORWARDED-FOR \"^" . $dhost . "\$\" DenyAccess" . PHP_EOL; //Ban IP from Proxy-User $host_rule .= "SetEnvIF X-CLUSTER-CLIENT-IP \"^" . $dhost . "\$\" DenyAccess" . PHP_EOL; //Ban IP for Cluster/Cloud-hosted WP-Installs $host_rule2 .= "deny from " . str_replace('.[0-9]+', '', trim($converted_host)) . PHP_EOL; } } $host_list .= $host_rule . PHP_EOL; //build large string of all hosts } else { /** * @todo warn the user the ip to be banned is whitelisted */ } } } //Process the agents list if (is_array($raw_agent_list)) { $count = 1; //to help us find the last one foreach ($raw_agent_list as $agent) { if (strlen(trim($agent)) > 1) { //if it isn't the last rule make sure we add an or if ($count < sizeof($agent)) { $end = ' [NC,OR]' . PHP_EOL; } else { $end = ' [NC]' . PHP_EOL; } if (strlen(trim($agent)) > 1) { if ($server_type === 'nginx') { //NGINX rule $converted_agent = 'if ($http_user_agent ~* "^' . quotemeta(trim($agent)) . '"){ return 403; }' . PHP_EOL; } else { //Rule for all other servers $converted_agent = 'RewriteCond %{HTTP_USER_AGENT} ^' . str_replace(' ', '\\ ', quotemeta(trim($agent))) . $end; } } $agent_list .= $converted_agent; //build large string of all agents } $count++; } } } $rules = ''; //initialize rules //Start with default rules if we have them if (strlen($default_list) > 1) { $rules .= $default_list; } //Add banned host lists if (strlen($host_list) > 1 || strlen($default_list)) { if (strlen($default_list) > 1) { $rules .= PHP_EOL; } if ($server_type === 'nginx' && strlen($host_list) > 1) { //NGINX rules $rules .= $host_list; } elseif (strlen($host_list) > 1) { $rules .= $host_list . 'order allow,deny' . PHP_EOL . 'deny from env=DenyAccess' . PHP_EOL . $host_rule2 . 'allow from all' . PHP_EOL; } } //Add banned user agents if (strlen($agent_list) > 1) { if (strlen($default_list) > 1 || strlen($host_list) > 1) { $rules .= PHP_EOL; } if ($server_type === 'nginx') { //NGINX rules $rules .= $agent_list; } else { $rules .= '<IfModule mod_rewrite.c>' . PHP_EOL; $rules .= 'RewriteEngine On' . PHP_EOL; $rules .= $agent_list; $rules .= 'RewriteRule ^(.*)$ - [F]' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL; } } if (strlen($rules) > 0) { $rules = explode(PHP_EOL, $rules); } else { $rules = false; } //create a proper array for writing return array('type' => 'htaccess', 'priority' => 1, 'name' => 'Ban Users', 'rules' => $rules); }