/** * Changes Admin User * * Changes the username and id of the 1st user * * @param string $username the username to change if changing at the same time * @param bool $id whether to change the id as well * * @return bool success or failure * **/ private function change_admin_user($username = null, $id = false) { global $wpdb; $itsec_files = ITSEC_Core::get_itsec_files(); if ($itsec_files->get_file_lock('admin_user')) { //make sure it isn't already running //sanitize the username $new_user = sanitize_text_field($username); //Get the full user object $user_object = get_user_by('id', '1'); if (!is_null($username) && validate_username($new_user) && false === username_exists($new_user)) { //there is a valid username to change if ($id === true) { //we're changing the id too so we'll set the username $user_login = $new_user; } else { // we're only changing the username //query main user table $wpdb->query("UPDATE `" . $wpdb->users . "` SET user_login = '******' WHERE user_login='******';"); if (is_multisite()) { //process sitemeta if we're in a multi-site situation $oldAdmins = $wpdb->get_var("SELECT meta_value FROM `" . $wpdb->sitemeta . "` WHERE meta_key = 'site_admins'"); $newAdmins = str_replace('5:"admin"', strlen($new_user) . ':"' . esc_sql($new_user) . '"', $oldAdmins); $wpdb->query("UPDATE `" . $wpdb->sitemeta . "` SET meta_value = '" . esc_sql($newAdmins) . "' WHERE meta_key = 'site_admins'"); } $itsec_files->release_file_lock('admin_user'); return true; } } elseif ($username !== null) { //username didn't validate $itsec_files->release_file_lock('admin_user'); return false; } else { //only changing the id $user_login = $user_object->user_login; } if ($id === true) { //change the user id $wpdb->query("DELETE FROM `" . $wpdb->users . "` WHERE ID = 1;"); $wpdb->insert($wpdb->users, array('user_login' => $user_login, 'user_pass' => $user_object->user_pass, 'user_nicename' => $user_object->user_nicename, 'user_email' => $user_object->user_email, 'user_url' => $user_object->user_url, 'user_registered' => $user_object->user_registered, 'user_activation_key' => $user_object->user_activation_key, 'user_status' => $user_object->user_status, 'display_name' => $user_object->display_name)); if (is_multisite() && $username !== null && validate_username($new_user)) { //process sitemeta if we're in a multi-site situation $oldAdmins = $wpdb->get_var("SELECT meta_value FROM `" . $wpdb->sitemeta . "` WHERE meta_key = 'site_admins'"); $newAdmins = str_replace('5:"admin"', strlen($new_user) . ':"' . esc_sql($new_user) . '"', $oldAdmins); $wpdb->query("UPDATE `" . $wpdb->sitemeta . "` SET meta_value = '" . esc_sql($newAdmins) . "' WHERE meta_key = 'site_admins'"); } $new_user = $wpdb->insert_id; $wpdb->query("UPDATE `" . $wpdb->posts . "` SET post_author = '" . $new_user . "' WHERE post_author = 1;"); $wpdb->query("UPDATE `" . $wpdb->usermeta . "` SET user_id = '" . $new_user . "' WHERE user_id = 1;"); $wpdb->query("UPDATE `" . $wpdb->comments . "` SET user_id = '" . $new_user . "' WHERE user_id = 1;"); $wpdb->query("UPDATE `" . $wpdb->links . "` SET link_owner = '" . $new_user . "' WHERE link_owner = 1;"); $itsec_files->release_file_lock('admin_user'); return true; } } return false; }
/** * Public function to get lock and call backup. * * Attempts to get a lock to prevent concurrant backups and calls the backup function itself. * * @since 4.0.0 * * @param boolean $one_time whether this is a one time backup * * @return mixed false on error or nothing */ public function do_backup($one_time = false) { ITSEC_Lib::set_minimum_memory_limit('256M'); $itsec_files = ITSEC_Core::get_itsec_files(); if ($itsec_files->get_file_lock('backup')) { $this->execute_backup($one_time); $itsec_files->release_file_lock('backup'); switch ($this->settings['method']) { case 0: return __('Backup complete. The backup was sent to the selected email recipients and was saved locally.', 'better-wp-security'); case 1: return __('Backup complete. The backup was sent to the selected email recipients.', 'better-wp-security'); default: return __('Backup complete. The backup was saved locally.', 'better-wp-security'); } } else { return new WP_Error('itsec-backup-do-backup-already-running', __('Unable to create a backup at this time since a backup is currently being created. If you wish to create an additional backup, please wait a few minutes before trying again.', 'better-wp-security')); } }
public function execute_file_check($scheduled_call = true, $return_data = false) { global $itsec_logger, $itsec_globals; if (false === $this->running) { $this->running = true; $send_email = true; ITSEC_Lib::set_minimum_memory_limit('256M'); $itsec_files = ITSEC_Core::get_itsec_files(); if ($itsec_files->get_file_lock('file_change', 300)) { //make sure it isn't already running define('ITSEC_DOING_FILE_CHECK', true); //figure out what chunk we're on if (isset($this->settings['split']) && true === $this->settings['split']) { if (isset($this->settings['last_chunk']) && false !== $this->settings['last_chunk'] && $this->settings['last_chunk'] < 6) { $chunk = $this->settings['last_chunk'] + 1; } else { $chunk = 0; } } else { $chunk = false; } if (false !== $chunk) { $db_field = 'itsec_local_file_list_' . $chunk; } else { $db_field = 'itsec_local_file_list'; } //set base memory $memory_used = @memory_get_peak_usage(); $logged_files = get_site_option($db_field); //if there are no old files old file list is an empty array if (false === $logged_files) { $send_email = false; $logged_files = array(); if (is_multisite()) { add_site_option($db_field, $logged_files); } else { add_option($db_field, $logged_files, '', 'no'); } } do_action('itsec-file-change-start-scan'); $current_files = $this->scan_files('', $scheduled_call, $chunk); //scan current files do_action('itsec-file-change-end-scan'); $files_added = @array_diff_assoc($current_files, $logged_files); //files added $files_removed = @array_diff_assoc($logged_files, $current_files); //files deleted $current_minus_added = @array_diff_key($current_files, $files_added); //remove all added files from current filelist $logged_minus_deleted = @array_diff_key($logged_files, $files_removed); //remove all deleted files from old file list $files_changed = array(); //array of changed files do_action('itsec-file-change-start-hash-comparisons'); //compare file hashes and mod dates foreach ($current_minus_added as $current_file => $current_attr) { if (array_key_exists($current_file, $logged_minus_deleted)) { //if attributes differ added to changed files array if (isset($current_attr['mod_date']) && 0 != strcmp($current_attr['mod_date'], $logged_minus_deleted[$current_file]['mod_date']) || 0 != strcmp($current_attr['d'], $logged_minus_deleted[$current_file]['d']) || (isset($current_attr['hash']) && 0 != strcmp($current_attr['hash'], $logged_minus_deleted[$current_file]['hash']) || 0 != strcmp($current_attr['h'], $logged_minus_deleted[$current_file]['h']))) { $remote_check = apply_filters('itsec_process_changed_file', true, $current_file, $current_attr['h']); //hook to run actions on a changed file at time of discovery if (true === $remote_check) { //don't list the file if it matches the WordPress.org hash $files_changed[$current_file]['h'] = isset($current_attr['hash']) ? $current_attr['hash'] : $current_attr['h']; $files_changed[$current_file]['d'] = isset($current_attr['mod_date']) ? $current_attr['mod_date'] : $current_attr['d']; } } } } //get count of changes $files_added_count = sizeof($files_added); $files_deleted_count = sizeof($files_removed); $files_changed_count = sizeof($files_changed); if (0 < $files_added_count) { $files_added = apply_filters('itsec_process_added_files', $files_added); //hook to run actions on all files added $files_added_count = sizeof($files_added); } if (0 < $files_deleted_count) { do_action('itsec_process_removed_files', $files_removed); //hook to run actions on all files removed } do_action('itsec-file-change-end-hash-comparisons'); //create single array of all changes $full_change_list = array('added' => $files_added, 'removed' => $files_removed, 'changed' => $files_changed); $this->settings['latest_changes'] = array('added' => count($files_added), 'removed' => count($files_removed), 'changed' => count($files_changed)); update_site_option($db_field, $current_files); //Cleanup variables when we're done with them unset($files_added); unset($files_removed); unset($files_changed); unset($current_files); $this->settings['last_run'] = $itsec_globals['current_time']; $this->settings['last_chunk'] = $chunk; ITSEC_Modules::set_settings('file-change', $this->settings); //get new max memory $check_memory = @memory_get_peak_usage(); if ($check_memory > $memory_used) { $memory_used = $check_memory - $memory_used; } $full_change_list['memory'] = round($memory_used / 1000000, 2); $itsec_logger->log_event('file_change', 8, $full_change_list); if (true === $send_email && false !== $scheduled_call && isset($this->settings['email']) && true === $this->settings['email'] && (0 < $files_added_count || 0 < $files_changed_count || 0 < $files_deleted_count)) { $email_details = array($files_added_count, $files_deleted_count, $files_changed_count, $full_change_list); $this->send_notification_email($email_details); } if (function_exists('get_current_screen') && (!isset(get_current_screen()->id) || false === strpos(get_current_screen()->id, 'security_page_toplevel_page_itsec_logs')) && isset($this->settings['notify_admin']) && true === $this->settings['notify_admin']) { ITSEC_Modules::set_setting('file-change', 'show_warning', true); } $itsec_files->release_file_lock('file_change'); if ($files_added_count > 0 || $files_changed_count > 0 || $files_deleted_count > 0) { $this->running = false; //There were changes found if ($return_data) { return $full_change_list; } else { return true; } } else { $this->running = false; return false; //No changes were found } } $this->running = false; return -1; //An error occured } return -1; }
/** * Locks out given user or host * * @since 4.0 * * @param string $type The type of lockout (for user reference) * @param string $reason Reason for lockout, for notifications * @param string $host Host to lock out * @param int $user user id to lockout * @param string $username username to lockout * * @return void */ private function lockout($type, $reason, $host = null, $user = null, $username = null) { global $wpdb, $itsec_logger, $itsec_globals; $itsec_files = ITSEC_Core::get_itsec_files(); $host_expiration = null; $user_expiration = null; $username = sanitize_text_field(trim($username)); if ($itsec_files->get_file_lock('lockout_' . $host . $user . $username)) { //Do we have a good host to lock out or not if (!is_null($host) && ITSEC_Lib::is_ip_whitelisted(sanitize_text_field($host)) === false && ITSEC_Lib_IP_Tools::validate($host)) { $good_host = sanitize_text_field($host); } else { $good_host = false; } //Do we have a valid user to lockout or not if ($user !== null && ITSEC_Lib::user_id_exists(intval($user)) === true) { $good_user = intval($user); } else { $good_user = false; } //Do we have a valid username to lockout or not if ($username !== null && $username != '') { $good_username = $username; } else { $good_username = false; } $blacklist_host = false; //assume we're not permanently blcking the host //Sanitize the data for later $type = sanitize_text_field($type); $reason = sanitize_text_field($reason); //handle a permanent host ban (if needed) if (ITSEC_Modules::get_setting('global', 'blacklist') && $good_host !== false) { //permanent blacklist $blacklist_period = ITSEC_Modules::get_setting('global', 'blacklist_period', 7); $blacklist_seconds = $blacklist_period * DAY_IN_SECONDS; $host_count = 1 + $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM `" . $wpdb->base_prefix . "itsec_lockouts` WHERE `lockout_expire_gmt` > '%s' AND `lockout_host`='%s';", date('Y-m-d H:i:s', $itsec_globals['current_time_gmt'] - $blacklist_seconds), $host)); if ($host_count >= ITSEC_Modules::get_setting('global', 'blacklist_count') && ITSEC_Files::can_write_to_files()) { $host_expiration = false; $this->blacklist_ip(sanitize_text_field($host)); $blacklist_host = true; //flag it so we don't do a temp ban as well } } //We have temp bans to perform if ($good_host !== false || $good_user !== false || $good_username || $good_username !== false) { if (ITSEC_Lib::is_ip_whitelisted(sanitize_text_field($host))) { $whitelisted = true; $expiration = date('Y-m-d H:i:s', 1); $expiration_gmt = date('Y-m-d H:i:s', 1); } else { $whitelisted = false; $exp_seconds = ITSEC_Modules::get_setting('global', 'lockout_period') * MINUTE_IN_SECONDS; $expiration = date('Y-m-d H:i:s', $itsec_globals['current_time'] + $exp_seconds); $expiration_gmt = date('Y-m-d H:i:s', $itsec_globals['current_time_gmt'] + $exp_seconds); } if ($good_host !== false && $blacklist_host === false) { //temp lockout host $host_expiration = $expiration; $wpdb->insert($wpdb->base_prefix . 'itsec_lockouts', array('lockout_type' => $type, 'lockout_start' => date('Y-m-d H:i:s', $itsec_globals['current_time']), 'lockout_start_gmt' => date('Y-m-d H:i:s', $itsec_globals['current_time_gmt']), 'lockout_expire' => $expiration, 'lockout_expire_gmt' => $expiration_gmt, 'lockout_host' => sanitize_text_field($host))); $itsec_logger->log_event('lockout', 10, array('expires' => $expiration, 'expires_gmt' => $expiration_gmt, 'type' => $type), sanitize_text_field($host)); } if ($good_user !== false) { //blacklist host and temp lockout user $user_expiration = $expiration; $wpdb->insert($wpdb->base_prefix . 'itsec_lockouts', array('lockout_type' => $type, 'lockout_start' => date('Y-m-d H:i:s', $itsec_globals['current_time']), 'lockout_start_gmt' => date('Y-m-d H:i:s', $itsec_globals['current_time_gmt']), 'lockout_expire' => $expiration, 'lockout_expire_gmt' => $expiration_gmt, 'lockout_host' => '', 'lockout_user' => intval($user))); if ($whitelisted === false) { $itsec_logger->log_event('lockout', 10, array('expires' => $expiration, 'expires_gmt' => $expiration_gmt, 'type' => $type), '', '', intval($user)); } else { $itsec_logger->log_event('lockout', 10, array(__('White Listed', 'better-wp-security'), 'type' => $type), '', '', intval($user)); } } if ($good_username !== false) { //blacklist host and temp lockout username $user_expiration = $expiration; $wpdb->insert($wpdb->base_prefix . 'itsec_lockouts', array('lockout_type' => $type, 'lockout_start' => date('Y-m-d H:i:s', $itsec_globals['current_time']), 'lockout_start_gmt' => date('Y-m-d H:i:s', $itsec_globals['current_time_gmt']), 'lockout_expire' => $expiration, 'lockout_expire_gmt' => $expiration_gmt, 'lockout_host' => '', 'lockout_username' => $username)); if ($whitelisted === false) { $itsec_logger->log_event('lockout', 10, array('expires' => $expiration, 'expires_gmt' => $expiration_gmt, 'type' => $type), '', '', $username); } else { $itsec_logger->log_event('lockout', 10, array(__('White Listed', 'better-wp-security'), 'type' => $type), '', '', $username); } } if ($whitelisted === false) { if (ITSEC_Modules::get_setting('global', 'email_notifications')) { //send email notifications $this->send_lockout_email($good_host, $good_user, $good_username, $host_expiration, $user_expiration, $reason); } if ($good_host !== false) { $itsec_files->release_file_lock('lockout_' . $host . $user . $username); $this->execute_lock(); } else { $itsec_files->release_file_lock('lockout_' . $host . $user . $username); $this->execute_lock(true); } } } $itsec_files->release_file_lock('lockout_' . $host . $user . $username); } }
/** * Uninstall execution * * @since 4.0 * * @return void * */ private function uninstall_execute() { global $itsec_globals, $wpdb; $this->deactivate_execute(); require_once $itsec_globals['plugin_dir'] . 'core/class-itsec-modules.php'; ITSEC_Modules::run_uninstall(); $itsec_files = ITSEC_Core::get_itsec_files(); $itsec_files->do_deactivate(); delete_site_option('itsec-storage'); delete_site_option('itsec_global'); delete_site_option('itsec_data'); delete_site_option('itsec_initials'); delete_site_option('itsec_jquery_version'); delete_site_option('itsec_message_queue'); $wpdb->query("DROP TABLE IF EXISTS " . $wpdb->base_prefix . "itsec_log;"); $wpdb->query("DROP TABLE IF EXISTS " . $wpdb->base_prefix . "itsec_lockouts;"); $wpdb->query("DROP TABLE IF EXISTS " . $wpdb->base_prefix . "itsec_temp;"); if (is_dir(ITSEC_Core::get_storage_dir())) { require_once ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-directory.php'; ITSEC_Lib_Directory::remove(ITSEC_Core::get_storage_dir()); } ITSEC_Lib::clear_caches(); }