/** * Build rewrite rules * * @since 4.0 * * @param array $input options to build rules from * * @return array rules to write */ public static function build_rewrite_rules($input = null) { $home_root = ITSEC_Lib::get_home_root(); $server_type = ITSEC_Lib::get_server(); //Get the server type to build the right rules //Get the rules from the database if input wasn't sent if ($input === null) { $input = get_site_option('itsec_hide_backend'); } $rules = ''; //initialize all rules to blank string //don't add any rules if the module hasn't been enabled if ($input['enabled'] == true) { if ($server_type == 'nginx') { $rules .= "\t# " . __('Rules to hide the dashboard', 'it-l10n-ithemes-security-pro') . PHP_EOL . "\trewrite ^(" . $home_root . ")?" . $input['slug'] . "/?\$ " . $home_root . "wp-login.php?\$query_string break;" . PHP_EOL; } else { $rules .= "\t# " . __('Rules to hide the dashboard', 'it-l10n-ithemes-security-pro') . PHP_EOL . "\tRewriteRule ^(" . $home_root . ")?" . $input['slug'] . "/?\$ " . $home_root . "wp-login.php [QSA,L]" . PHP_EOL; } if ($input['register'] != 'wp-register.php') { if ($server_type == 'nginx') { $rules .= "\trewrite ^(" . $home_root . ")?" . $input['register'] . "/?\$ " . $home_root . $input['slug'] . "?action=register break;" . PHP_EOL; } else { $rules .= "\tRewriteRule ^(" . $home_root . ")?" . $input['register'] . "/?\$ /wplogin?action=register [QSA,L]" . 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' => 9, 'name' => 'Hide Backend', 'rules' => $rules); }
protected function sanitize_settings() { if (is_dir(WP_PLUGIN_DIR . '/iwp-client')) { $this->sanitize_setting('bool', 'infinitewp_compatibility', __('Add InfiniteWP Compatibility', 'better-wp-security')); } else { $this->settings['infinitewp_compatibility'] = $this->previous_settings['infinitewp_compatibility']; } if ('nginx' === ITSEC_Lib::get_server()) { $this->sanitize_setting('writable-file', 'nginx_file', __('NGINX Conf File', 'better-wp-security'), false); } else { $this->settings['nginx_file'] = $this->previous_settings['nginx_file']; } $this->set_previous_if_empty(array('did_upgrade', 'log_info', 'show_new_dashboard_notice', 'show_security_check')); $this->set_default_if_empty(array('log_location', 'nginx_file')); $this->sanitize_setting('bool', 'write_files', __('Write to Files', 'better-wp-security')); $this->sanitize_setting('bool', 'digest_email', __('Send Digest Email', 'better-wp-security')); $this->sanitize_setting('bool', 'blacklist', __('Blacklist Repeat Offender', 'better-wp-security')); $this->sanitize_setting('bool', 'email_notifications', __('Email Lockout Notifications', 'better-wp-security')); $this->sanitize_setting('bool', 'allow_tracking', __('Allow Data Tracking', 'better-wp-security')); $this->sanitize_setting('bool', 'lock_file', __('Disable File Locking', 'better-wp-security')); $this->sanitize_setting('bool', 'proxy_override', __('Override Proxy Detection', 'better-wp-security')); $this->sanitize_setting('bool', 'hide_admin_bar', __('Hide Security Menu in Admin Bar', 'better-wp-security')); $this->sanitize_setting('bool', 'show_error_codes', __('Show Error Codes', 'better-wp-security')); $this->sanitize_setting('string', 'lockout_message', __('Host Lockout Message', 'better-wp-security')); $this->sanitize_setting('string', 'user_lockout_message', __('User Lockout Message', 'better-wp-security')); $this->sanitize_setting('string', 'community_lockout_message', __('Community Lockout Message', 'better-wp-security')); $this->sanitize_setting('writable-directory', 'log_location', __('Path to Log Files', 'better-wp-security')); $this->sanitize_setting('positive-int', 'blacklist_count', __('Blacklist Threshold', 'better-wp-security')); $this->sanitize_setting('positive-int', 'blacklist_period', __('Blacklist Lockout Period', 'better-wp-security')); $this->sanitize_setting('positive-int', 'lockout_period', __('Lockout Period', 'better-wp-security')); $this->sanitize_setting('positive-int', 'log_rotation', __('Days to Keep Database Logs', 'better-wp-security')); $log_types = array_keys($this->get_valid_log_types()); $this->sanitize_setting($log_types, 'log_type', __('Log Type', 'better-wp-security')); $this->sanitize_setting('newline-separated-ips', 'lockout_white_list', __('Lockout White List', 'better-wp-security')); $this->sanitize_setting('newline-separated-emails', 'notification_email', __('Notification Email', 'better-wp-security')); $this->sanitize_setting('newline-separated-emails', 'backup_email', __('Backup Delivery Email', 'better-wp-security')); $allowed_tags = array('a' => array('href' => array(), 'title' => array()), 'br' => array(), 'em' => array(), 'strong' => array(), 'h1' => array(), 'h2' => array(), 'h3' => array(), 'h4' => array(), 'h5' => array(), 'h6' => array(), 'div' => array('style' => array())); $this->settings['lockout_message'] = trim(wp_kses($this->settings['lockout_message'], $allowed_tags)); $this->settings['user_lockout_message'] = trim(wp_kses($this->settings['user_lockout_message'], $allowed_tags)); $this->settings['community_lockout_message'] = trim(wp_kses($this->settings['community_lockout_message'], $allowed_tags)); }
/** * Setup and call admin messages. * * Sets up messages and registers actions for WordPress admin messages. * * @since 4.0 * * @param object $messages WordPress error object or string of message to display * * @return void */ public function show_network_admin_notice($errors) { global $itsec_saved_network_notices; //use global to transfer to add_action callback $itsec_saved_network_notices = ''; //initialize so we can get multiple error messages (if needed) if (function_exists('apc_store')) { apc_clear_cache(); //Let's clear APC (if it exists) when big stuff is saved. } if ((!defined('DOING_AJAX') || DOING_AJAX == false) && function_exists('get_current_screen') && isset(get_current_screen()->id) && (strpos(get_current_screen()->id, 'security_page_toplevel_page_itsec_settings') !== false || strpos(get_current_screen()->id, 'security_page_toplevel_page_itsec_advanced') !== false || strpos(get_current_screen()->id, 'security_page_toplevel_page_itsec_pro') !== false)) { if ($errors === false && isset($_GET['settings-updated']) && sanitize_text_field($_GET['settings-updated']) == 'true') { $updated = ''; if (get_site_option('itsec_manual_update') == true) { delete_site_option('itsec_manual_update'); if (ITSEC_Lib::get_server() == 'nginx') { $server = __('NGINX conf file and/or restart your NGINX server', 'it-l10n-better-wp-security'); } else { $server = __('.htaccess file', 'it-l10n-better-wp-security'); } $updated = sprintf('<br />%s %s %s', __('As you have not allowed this plugin to update system files you must update your', 'it-l10n-better-wp-security'), $server, __('as well as your wp-config.php file manually. Rules to insert in both files can be found on the Dashboard page.', 'it-l10n-better-wp-security')); } $itsec_saved_network_notices = '<div id="setting-error-settings_updated" class="updated settings-error"><p><strong>' . __('Settings Updated', 'it-l10n-better-wp-security') . $updated . '</strong></p></div>'; } elseif (is_wp_error($errors)) { //see if object is even an error $error_messages = $errors->get_error_messages(); //get all errors if it is $type = key($errors->errors); foreach ($error_messages as $error) { $itsec_saved_network_notices = '<div id="setting-error-settings_updated" class="' . sanitize_text_field($type) . ' settings-error"><p><strong>' . sanitize_text_field($error) . '</strong></p></div>'; } } //register appropriate message actions add_action('admin_notices', array($this, 'print_network_admin_notice')); add_action('network_admin_notices', array($this, 'print_network_admin_notice')); } }
/** * Execute admin initializations * * @return void */ public function initialize_admin() { add_settings_section( 'tweaks_server', __( 'Configure Server Tweaks', 'it-l10n-ithemes-security-pro' ), '__return_empty_string', 'security_page_toplevel_page_itsec_settings' ); add_settings_section( 'tweaks_wordpress', __( 'Configure WordPress Tweaks', 'it-l10n-ithemes-security-pro' ), '__return_empty_string', 'security_page_toplevel_page_itsec_settings' ); add_settings_section( 'tweaks_multisite', __( 'Configure Multisite Tweaks', 'it-l10n-ithemes-security-pro' ), '__return_empty_string', 'security_page_toplevel_page_itsec_settings' ); //Add settings fields add_settings_field( 'itsec_tweaks[protect_files]', __( 'System Files', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_server_protect_files' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_server' ); if ( ITSEC_Lib::get_server() != 'nginx' ) { add_settings_field( 'itsec_tweaks[directory_browsing]', __( 'Directory Browsing', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_server_directory_browsing' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_server' ); } add_settings_field( 'itsec_tweaks[request_methods]', __( 'Request Methods', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_server_request_methods' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_server' ); add_settings_field( 'itsec_tweaks[suspicious_query_strings]', __( 'Suspicious Query Strings', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_server_suspicious_query_strings' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_server' ); add_settings_field( 'itsec_tweaks[non_english_characters]', __( 'Non-English Characters', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_server_non_english_characters' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_server' ); add_settings_field( 'itsec_tweaks[long_url_strings]', __( 'Long URL Strings', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_server_long_url_strings' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_server' ); add_settings_field( 'itsec_tweaks[write_permissions]', __( 'File Writing Permissions', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_server_write_permissions' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_server' ); add_settings_field( 'itsec_tweaks[uploads_php]', __( 'Uploads', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_uploads_php' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_server' ); add_settings_field( 'itsec_tweaks[wlwmanifest_header]', __( 'Windows Live Writer Header', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_wlwmanifest_header' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_wordpress' ); add_settings_field( 'itsec_tweaks[edituri_header]', __( 'EditURI Header', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_edituri_header' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_wordpress' ); add_settings_field( 'itsec_tweaks[comment_spam]', __( 'Comment Spam', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_comment_spam' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_wordpress' ); add_settings_field( 'itsec_tweaks[file_editor]', __( 'File Editor', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_file_editor' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_wordpress' ); add_settings_field( 'itsec_tweaks[disable_xmlrpc]', __( 'XML-RPC', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_disable_xmlrpc' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_wordpress' ); add_settings_field( 'itsec_tweaks[allow_xmlrpc_multiauth]', __( 'Multiple Authentication Attempts per XML-RPC Request', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_allow_xmlrpc_multiauth' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_wordpress' ); add_settings_field( 'itsec_tweaks[safe_jquery]', __( 'Replace jQuery With a Safe Version', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_safe_jquery' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_wordpress' ); add_settings_field( 'itsec_tweaks[login_errors]', __( 'Login Error Messages', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_login_errors' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_wordpress' ); add_settings_field( 'itsec_tweaks[force_unique_nicename]', __( 'Force Unique Nickname', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_force_unique_nicename' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_wordpress' ); add_settings_field( 'itsec_tweaks[disable_unused_author_pages]', __( 'Disable Extra User Archives', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_disable_unused_author_pages' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_wordpress' ); if ( is_multisite() ) { add_settings_field( 'itsec_tweaks[theme_updates]', __( 'Theme Update Notifications', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_theme_updates' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_multisite' ); add_settings_field( 'itsec_tweaks[plugin_updates]', __( 'Plugin Update Notifications', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_plugin_updates' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_multisite' ); add_settings_field( 'itsec_tweaks[core_updates]', __( 'Core Update Notifications', 'it-l10n-ithemes-security-pro' ), array( $this, 'tweaks_wordpress_core_updates' ), 'security_page_toplevel_page_itsec_settings', 'tweaks_multisite' ); } //Register the settings field for the entire module register_setting( 'security_page_toplevel_page_itsec_settings', 'itsec_tweaks', array( $this, 'sanitize_module_input' ) ); }
/** * Gets location of .htaccess * * Finds and returns path to .htaccess or nginx.conf if appropriate * * @since 4.0.0 * * @return string path to .htaccess */ public static function get_htaccess() { global $itsec_globals; if ('nginx' === ITSEC_Lib::get_server()) { return $itsec_globals['settings']['nginx_file']; } else { return ITSEC_Lib::get_home_path() . '.htaccess'; } }
/** * Process quick ban of host. * * Immediately adds the supplied host to the .htaccess file for banning. * * @since 4.0.0 * * @param string $host the host to ban * * @return bool true on success or false on failure */ public static function quick_ban($host) { $host = trim($host); if (!class_exists('ITSEC_Lib_IP_Tools')) { $itsec_core = ITSEC_Core::get_instance(); require_once dirname($itsec_core->get_plugin_file()) . '/core/lib/class-itsec-lib-ip-tools.php'; } if (!ITSEC_Lib_IP_Tools::validate($host)) { return false; } $host_rule = '# ' . __('Quick ban IP. Will be updated on next formal rules save.', 'better-wp-security') . "\n"; if ('nginx' === ITSEC_Lib::get_server()) { $host_rule .= "\tdeny {$host};\n"; } else { if ('apache' === ITSEC_Lib::get_server()) { $dhost = str_replace('.', '\\.', $host); //re-define $dhost to match required output for SetEnvIf-RegEX $host_rule .= "SetEnvIF REMOTE_ADDR \"^{$dhost}\$\" DenyAccess\n"; //Ban IP $host_rule .= "SetEnvIF X-FORWARDED-FOR \"^{$dhost}\$\" DenyAccess\n"; //Ban IP from Proxy-User $host_rule .= "SetEnvIF X-CLUSTER-CLIENT-IP \"^{$dhost}\$\" DenyAccess\n"; //Ban IP for Cluster/Cloud-hosted WP-Installs $host_rule .= "<IfModule mod_authz_core.c>\n"; $host_rule .= "\t<RequireAll>\n"; $host_rule .= "\t\tRequire all granted\n"; $host_rule .= "\t\tRequire not env DenyAccess\n"; $host_rule .= "\t\tRequire not ip {$host}\n"; $host_rule .= "\t</RequireAll>\n"; $host_rule .= "</IfModule>\n"; $host_rule .= "<IfModule !mod_authz_core.c>\n"; $host_rule .= "\tOrder allow,deny\n"; $host_rule .= "\tDeny from env=DenyAccess\n"; $host_rule .= "\tDeny from {$host}\n"; $host_rule .= "\tAllow from all\n"; $host_rule .= "</IfModule>\n"; } } require_once trailingslashit($GLOBALS['itsec_globals']['plugin_dir']) . 'core/lib/class-itsec-lib-config-file.php'; $result = ITSEC_Lib_Config_File::append_server_config($host_rule); if (is_wp_error($result)) { return false; } return true; }
public function release_lockout() { global $wpdb, $itsec_globals; if (!class_exists('ITSEC_Lib')) { require trailingslashit($itsec_globals['plugin_dir']) . '/core/class-itsec-lib.php'; } $lockout_ids = $_POST['lockout_ids']; if (!is_array($lockout_ids)) { $lockout_ids = array(); } $type = 'updated'; $message = __('The selected lockouts have been cleared.', 'better-wp-security'); foreach ($lockout_ids as $value) { $wpdb->update($wpdb->base_prefix . 'itsec_lockouts', array('lockout_active' => 0), array('lockout_id' => intval($value))); } ITSEC_Lib::clear_caches(); if (!is_multisite()) { if (!function_exists('add_settings_error')) { require_once ABSPATH . '/wp-admin/includes/template.php'; } add_settings_error('itsec', esc_attr('settings_updated'), $message, $type); } $site_status = array('username_admin_exists' => username_exists('admin') ? 1 : 0, 'user_id1_exists' => ITSEC_Lib::user_id_exists(1) ? 1 : 0, 'backup' => $this->backup_status(), 'permalink_structure' => get_option('permalink_structure'), 'is_multisite' => is_multisite() ? 1 : 0, 'users_can_register' => get_site_option('users_can_register') ? 1 : 0, 'force_ssl_login' => defined('FORCE_SSL_LOGIN') && FORCE_SSL_LOGIN === true ? 1 : 0, 'force_ssl_admin' => defined('FORCE_SSL_ADMIN') && FORCE_SSL_ADMIN === true ? 1 : 0, 'server_nginx' => 'nginx' === ITSEC_Lib::get_server() ? 1 : 0, 'lockouts_host' => $this->get_lockouts('host', true), 'lockouts_user' => $this->get_lockouts('user', true), 'lockouts_username' => $this->get_lockouts('username', true)); return array('result' => 'success', 'site_status' => $site_status); }
/** * Gets location of .htaccess * * Finds and returns path to .htaccess or nginx.conf if appropriate * * @return string path to .htaccess * * */ public static function get_htaccess() { global $itsec_globals; if (ITSEC_Lib::get_server() === 'nginx') { return $itsec_globals['settings']['nginx_file']; } else { return ABSPATH . '.htaccess'; } }
/** * echos write files Field * * @since 4.0 * * @return void */ public function settings_field_write_files() { global $itsec_globals; if (isset($this->settings['write_files']) && $this->settings['write_files'] === true) { $write_files = 1; } else { $write_files = 0; } if (ITSEC_Lib::get_server() == 'nginx') { $server_file = ''; } else { $server_file = ' and .htaccess'; } echo '<input type="checkbox" id="itsec_global_write_files" name="itsec_global[write_files]" value="1" ' . checked(1, $write_files, false) . '/>'; printf('<label for="itsec_global_write_files">%s %s %s%s.</label>', __('Allow', 'better-wp-security'), $itsec_globals['plugin_name'], __('to write to wp-config.php', 'better-wp-security'), $server_file); printf('<p class="description">%s %s %s%s%s</p>', __('Whether or not', 'better-wp-security'), $itsec_globals['plugin_name'], __('should be allowed to write to wp-config.php', 'better-wp-security'), $server_file, __(' automatically. If disabled you will need to manually place configuration options in those files.', 'better-wp-security')); }
/** * 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); }
/** * Process quick ban of host. * * Immediately adds the supplied host to the .htaccess file for banning. * * @since 4.0.0 * * @param string $host the host to ban * * @return bool true on success or false on failure */ public static function quick_ban( $host ) { $host = trim( $host ); if ( ! ITSEC_Lib::validates_ip_address( $host ) ) { return false; } $host_rule = '# ' . __( 'Quick ban IP. Will be updated on next formal rules save.', 'it-l10n-ithemes-security-pro' ) . "\n"; if ( 'nginx' === ITSEC_Lib::get_server() ) { $host_rule .= "\tdeny $host;\n"; } else if ( 'apache' === ITSEC_Lib::get_server() ) { $dhost = str_replace( '.', '\\.', $host ); //re-define $dhost to match required output for SetEnvIf-RegEX $host_rule .= "SetEnvIF REMOTE_ADDR \"^$dhost$\" DenyAccess\n"; //Ban IP $host_rule .= "SetEnvIF X-FORWARDED-FOR \"^$dhost$\" DenyAccess\n"; //Ban IP from Proxy-User $host_rule .= "SetEnvIF X-CLUSTER-CLIENT-IP \"^$dhost$\" DenyAccess\n"; //Ban IP for Cluster/Cloud-hosted WP-Installs $host_rule .= "<IfModule mod_authz_core.c>\n"; $host_rule .= "\t<RequireAll>\n"; $host_rule .= "\t\tRequire all granted\n"; $host_rule .= "\t\tRequire not env DenyAccess\n"; $host_rule .= "\t\tRequire not ip $host\n"; $host_rule .= "\t</RequireAll>\n"; $host_rule .= "</IfModule>\n"; $host_rule .= "<IfModule !mod_authz_core.c>\n"; $host_rule .= "\tOrder allow,deny\n"; $host_rule .= "\tDeny from env=DenyAccess\n"; $host_rule .= "\tDeny from $host\n"; $host_rule .= "\tAllow from all\n"; $host_rule .= "</IfModule>\n"; } require_once( trailingslashit( $GLOBALS['itsec_globals']['plugin_dir'] ) . 'core/lib/class-itsec-lib-config-file.php' ); $result = ITSEC_Lib_Config_File::append_server_config( $host_rule ); if ( is_wp_error( $result ) ) { return false; } return true; }
/** * Saves all rewrite rules to htaccess or similar file. * * Gets a file lock for .htaccess and calls the writing function if successful. * * @since 4.0 * * @return mixed array or false if writing disabled or error message */ public function save_rewrites() { global $itsec_globals; if (!is_array($this->file_modules)) { return; } foreach ($this->file_modules as $module) { if (isset($module['rewrite'])) { call_user_func_array($module['rewrite'], array()); } } if (ITSEC_Lib::get_server() == 'nginx' || isset($itsec_globals['settings']['write_files']) && $itsec_globals['settings']['write_files'] === true) { $success = $this->write_rewrites(); //save the return value for success/error flag if ($success === true) { if (ITSEC_Lib::get_server() == 'nginx') { return array('success' => true, 'text' => sprintf('%s %s. %s', __('Your rewrite rules have been saved to', 'it-l10n-better-wp-security'), $itsec_globals['settings']['nginx_file'], __('You must restart your NGINX server for the settings to take effect', 'it-l10n-better-wp-security'))); } else { return array('success' => true, 'text' => true); } } else { return array('success' => false, 'text' => __('Unable to write to your .htaccess or nginx.conf file. If the problem persists contact support.', 'it-l10n-better-wp-security')); } } else { return false; } }
protected function render_settings($form) { $validator = ITSEC_Modules::get_validator($this->id); $log_types = $validator->get_valid_log_types(); $show_error_codes_options = array(false => __('No (default)'), true => __('Yes')); ?> <table class="form-table itsec-settings-section"> <tr> <th scope="row"><label for="itsec-global-write_files"><?php _e('Write to Files', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_checkbox('write_files'); ?> <label for="itsec-global-write_files"><?php _e('Allow iThemes Security to write to wp-config.php and .htaccess.', 'better-wp-security'); ?> </label> <p class="description"><?php _e('Whether or not iThemes Security should be allowed to write to wp-config.php and .htaccess automatically. If disabled you will need to manually place configuration options in those files.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-notification_email"><?php _e('Notification Email', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_textarea('notification_email', array('class' => 'textarea-small')); ?> <p class="description"><?php _e('The email address(es) all security notifications will be sent to. One address per line.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-digest_email"><?php _e('Send Digest Email', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_checkbox('digest_email'); ?> <label for="itsec-global-digest_email"><?php _e('Send digest email', 'better-wp-security'); ?> </label> <p class="description"><?php _e('During periods of heavy attack or other times a security plugin can generate a LOT of email just telling you that it is doing its job. Turning this on will reduce the emails from this plugin to no more than one per day for any notification.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-backup_email"><?php _e('Backup Delivery Email', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_textarea('backup_email', array('class' => 'textarea-small')); ?> <br /> <p class="description"><?php _e('The email address(es) all database backups will be sent to. One address per line.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-lockout_message"><?php _e('Host Lockout Message', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_textarea('lockout_message', array('class' => 'widefat')); ?> <p class="description"><?php _e('The message to display when a computer (host) has been locked out.', 'better-wp-security'); ?> </p> <p class="description"><?php _e('You can use HTML in your message. Allowed tags include: a, br, em, strong, h1, h2, h3, h4, h5, h6, div.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-user_lockout_message"><?php _e('User Lockout Message', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_textarea('user_lockout_message', array('class' => 'widefat')); ?> <p class="description"><?php _e('The message to display to a user when their account has been locked out.', 'better-wp-security'); ?> </p> <p class="description"><?php _e('You can use HTML in your message. Allowed tags include: a, br, em, strong, h1, h2, h3, h4, h5, h6, div.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-community_lockout_message"><?php _e('Community Lockout Message', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_textarea('community_lockout_message', array('class' => 'widefat')); ?> <p class="description"><?php _e('The message to display to a user when their IP has been flagged as bad by the iThemes network.', 'better-wp-security'); ?> </p> <p class="description"><?php _e('You can use HTML in your message. Allowed tags include: a, br, em, strong, h1, h2, h3, h4, h5, h6, div.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-blacklist"><?php _e('Blacklist Repeat Offender', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_checkbox('blacklist'); ?> <label for="itsec-global-blacklist"><?php _e('Enable Blacklist Repeat Offender', 'better-wp-security'); ?> </label> <p class="description"><?php _e('If this box is checked the IP address of the offending computer will be added to the "Ban Users" blacklist after reaching the number of lockouts listed below.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-blacklist_count"><?php _e('Blacklist Threshold', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_text('blacklist_count', array('class' => 'small-text')); ?> <label for="itsec-global-blacklist_count"><?php _e('Lockouts', 'better-wp-security'); ?> </label> <p class="description"><?php _e('The number of lockouts per IP before the host is banned permanently from this site.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-blacklist_period"><?php _e('Blacklist Lookback Period', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_text('blacklist_period', array('class' => 'small-text')); ?> <label for="itsec-global-blacklist_period"><?php _e('Days', 'better-wp-security'); ?> </label> <p class="description"><?php _e('How many days should a lockout be remembered to meet the blacklist count above.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-lockout_period"><?php _e('Lockout Period', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_text('lockout_period', array('class' => 'small-text')); ?> <label for="itsec-global-lockout_period"><?php _e('Minutes', 'better-wp-security'); ?> </label> <p class="description"><?php _e('The length of time a host or user will be banned from this site after hitting the limit of bad logins.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-lockout_white_list"><?php _e('Lockout White List', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_textarea('lockout_white_list'); ?> <p><?php $form->add_button('add-to-whitelist', array('value' => __('Add my current IP to the White List', 'better-wp-security'), 'class' => 'button-primary')); ?> </p> <p class="description"><?php _e('Use the guidelines below to enter hosts that will not be locked out from your site. This will keep you from locking yourself out of any features if you should trigger a lockout. Please note this does not override away mode and will only prevent a temporary ban. Should a permanent ban be triggered you will still be added to the "Ban Users" list unless the IP address is also white listed in that section.', 'better-wp-security'); ?> </p> <ul> <li> <?php _e('You may white list users by individual IP address or IP address range using wildcards or CIDR notation.', 'better-wp-security'); ?> <ul> <li><?php _e('Individual IP addresses must be in IPv4 or IPv6 standard format (###.###.###.### or ####:####:####:####:####:####:####:####).', 'better-wp-security'); ?> </li> <li><?php _e('CIDR notation is allowed to specify a range of IP addresses (###.###.###.###/## or ####:####:####:####:####:####:####:####/###).', 'better-wp-security'); ?> </li> <li><?php _e('Wildcards are also supported with some limitations. If using wildcards (*), you must start with the right-most chunk in the IP address. For example ###.###.###.* and ###.###.*.* are permitted but ###.###.*.### is not. Wildcards are only for convenient entering of IP addresses, and will be automatically converted to their appropriate CIDR notation format on save.', 'better-wp-security'); ?> </li> </ul> </li> <li><?php _e('Enter only 1 IP address or 1 IP address range per line.', 'better-wp-security'); ?> </li> </ul> <p><a href="http://ip-lookup.net/domain-lookup.php" target="_blank"><?php _e('Lookup IP Address.', 'better-wp-security'); ?> </a></p> <p class="description"><strong><?php _e('This white list will prevent any IP listed from triggering an automatic lockout. You can still block the IP address manually in the banned users settings.', 'better-wp-security'); ?> </strong></p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-email_notifications"><?php _e('Email Lockout Notifications', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_checkbox('email_notifications'); ?> <label for="itsec-global-email_notifications"><?php _e('Enable Email Lockout Notifications', 'better-wp-security'); ?> </label> <p class="description"><?php _e('This feature will trigger an email to be sent to the email addresses listed in the Notification Email setting whenever a host or user is locked out of the system.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-log_type"><?php _e('Log Type', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_select('log_type', $log_types); ?> <label for="itsec-global-log_type"><?php _e('How should even logs be kept', 'better-wp-security'); ?> </label> <p class="description"><?php _e('iThemes Security can log events in multiple ways, each with advantages and disadvantages. Database Only puts all events in the database with your posts and other WordPress data. This makes it easy to retrieve and process but can be slower if the database table gets very large. File Only is very fast but the plugin does not process the logs itself as that would take far more resources. For most users or smaller sites Database Only should be fine. If you have a very large site or a log processing software then File Only might be a better option.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-log_rotation"><?php _e('Days to Keep Database Logs', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_text('log_rotation', array('class' => 'small-text')); ?> <label for="itsec-global-log_rotation"><?php _e('Days', 'better-wp-security'); ?> </label> <p class="description"><?php _e('The number of days database logs should be kept. File logs will be kept indefinitely but will be rotated once the file hits 10MB.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-log_location"><?php _e('Path to Log Files', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_text('log_location', array('class' => 'large-text code')); ?> <p><label for="itsec-global-log_location"><?php _e('The path on your server where log files should be stored.', 'better-wp-security'); ?> </label></p> <p class="description"><?php _e('This path must be writable by your website. For added security, it is recommended you do not include it in your website root folder.', 'better-wp-security'); ?> </p> <p><?php $form->add_button('reset-log-location', array('value' => __('Restore Default Log File Path', 'better-wp-security'), 'class' => 'button-secondary')); ?> </p> </td> </tr> <?php if (is_dir(WP_PLUGIN_DIR . '/iwp-client')) { ?> <tr> <th scope="row"><label for="itsec-global-infinitewp_compatibility"><?php _e('Add InfiniteWP Compatibility', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_checkbox('infinitewp_compatibility'); ?> <label for="itsec-global-infinitewp_compatibility"><?php _e('Enable InfiniteWP Compatibility', 'better-wp-security'); ?> </label> <p class="description"><?php printf(__('Turning this feature on will enable compatibility with <a href="%s" target="_blank">InfiniteWP</a>. Do not turn it on unless you use the InfiniteWP service.', 'better-wp-security'), 'http://infinitewp.com'); ?> </p> </td> </tr> <?php } ?> <tr> <th scope="row"><label for="itsec-global-allow_tracking"><?php _e('Allow Data Tracking', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_checkbox('allow_tracking'); ?> <label for="itsec-global-allow_tracking"><?php _e('Allow iThemes to track plugin usage via anonymous data.', 'better-wp-security'); ?> </label> </td> </tr> <?php if ('nginx' === ITSEC_Lib::get_server()) { ?> <tr> <th scope="row"><label for="itsec-global-nginx_file"><?php _e('NGINX Conf File', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_text('nginx_file', array('class' => 'large-text code')); ?> <p><label for="itsec-global-nginx_file"><?php _e('The path on your server where the nginx config file is located.', 'better-wp-security'); ?> </label></p> <p class="description"><?php _e('This path must be writable by your website. For added security, it is recommended you do not include it in your website root folder.', 'better-wp-security'); ?> </p> </td> </tr> <?php } ?> <tr> <th scope="row"><label for="itsec-global-lock_file"><?php _e('Disable File Locking', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_checkbox('lock_file'); ?> <label for="itsec-global-lock_file"><?php _e('Disable File Locking', 'better-wp-security'); ?> </label> <p class="description"><?php _e('Turning this option on will prevent errors related to file locking however might result in operations being executed twice. We do not recommend turning this off unless your host prevents the file locking feature from working correctly.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-proxy_override"><?php _e('Override Proxy Detection', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_checkbox('proxy_override'); ?> <label for="itsec-global-proxy_override"><?php _e('Disable Proxy IP Detection', 'better-wp-security'); ?> </label> <p class="description"><?php _e('If you\'re not using a proxy service such as Varnish, Cloudflare or others turning this on may result in more accurate IP detection.', 'better-wp-security'); ?> </p> </td> </tr> <tr> <th scope="row"><label for="itsec-global-hide_admin_bar"><?php _e('Hide Security Menu in Admin Bar', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_checkbox('hide_admin_bar'); ?> <label for="itsec-global-hide_admin_bar"><?php _e('Hide security menu in admin bar.', 'better-wp-security'); ?> </label> </td> </tr> <tr> <th scope="row"><label for="itsec-global-show_error_codes"><?php _e('Show Error Codes', 'better-wp-security'); ?> </label></th> <td> <?php $form->add_select('show_error_codes', $show_error_codes_options); ?> <p class="description"><?php _e('Each error message in iThemes Security has an associated error code that can help diagnose an issue. Changing this setting to "Yes" causes these codes to display. This setting should be left set to "No" unless iThemes Security support requests that you change it.', 'better-wp-security'); ?> </p> </td> </tr> </table> <?php }