/**
  * 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);
 }
Example #2
0
 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;
     }
 }
Example #13
0
    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 
    }