/** * Returns directory contents * * @since 4.3 * * @param string $dir the directory to scan * @param string $parent the parent directory (if needed * * @return array */ private function get_files($dir = '', $parent = null) { if ($parent === null) { $parent = ITSEC_Lib::get_home_path(); } $rel_dir = trim(sanitize_text_field($dir)); $directory = trim(trailingslashit(urldecode(trailingslashit(sanitize_text_field($parent)) . $rel_dir))); $dir_contents = array(); if (file_exists($directory)) { $files = scandir($directory); natcasesort($files); if (count($files) > 2) { /* The 2 accounts for . and .. */ //two loops keep directories sorted before files // All dirs foreach ($files as $file) { if (file_exists($directory . $file) && $file != '.' && $file != '..' && is_dir($directory . $file)) { //echo $dir . ', ' . $directory . PHP_EOL; $dir_contents[$file] = $this->get_files($file, $directory); } } // All files foreach ($files as $file) { if (file_exists($directory . $file) && $file != '.' && $file != '..' && !is_dir($directory . $file)) { //echo $file . PHP_EOL; $dir_contents[] = $file; } } } } return $dir_contents; }
/** * Add Files Admin Javascript * * @since 4.0 * * @return void */ public function admin_enqueue_scripts() { global $itsec_globals; wp_enqueue_script('itsec_file_change_warning_js', $this->module_path . 'js/admin-file-change-warning.js', array('jquery'), $itsec_globals['plugin_build']); wp_localize_script('itsec_file_change_warning_js', 'itsec_file_change_warning', array('nonce' => wp_create_nonce('itsec_file_change_warning'), 'url' => admin_url() . 'admin.php?page=toplevel_page_itsec_logs&itsec_log_filter=file_change')); if (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_logs') !== false || strpos(get_current_screen()->id, 'dashboard') !== false)) { wp_enqueue_script('itsec_file_change_js', $this->module_path . 'js/admin-file-change.js', array('jquery'), $itsec_globals['plugin_build']); wp_localize_script('itsec_file_change_js', 'itsec_file_change', array('mem_limit' => ITSEC_Lib::get_memory_limit(), 'text' => __('Warning: Your server has less than 128MB of RAM dedicated to PHP. If you have many files in your installation or a lot of active plugins activating this feature may result in your site becoming disabled with a memory error. See the plugin homepage for more information.', 'it-l10n-better-wp-security'), 'module_path' => $this->module_path, 'button_text' => isset($this->settings['split']) && $this->settings['split'] === true ? __('Scan Next File Chunk', 'it-l10n-better-wp-security') : __('Scan Files Now', 'it-l10n-better-wp-security'), 'scanning_button_text' => __('Scanning...', 'it-l10n-better-wp-security'), 'no_changes' => __('No changes were detected.', 'it-l10n-better-wp-security'), 'changes' => __('Changes were detected. Please check the log page for details.', 'it-l10n-better-wp-security'), 'error' => __('An error occured. Please try again later', 'it-l10n-better-wp-security'), 'ABSPATH' => ITSEC_Lib::get_home_path(), 'nonce' => wp_create_nonce('itsec_do_file_check'))); wp_enqueue_script('itsec_jquery_filetree', $this->module_path . 'filetree/jqueryFileTree.js', array('jquery'), '1.01'); wp_localize_script('itsec_jquery_filetree', 'itsec_jquery_filetree', array('nonce' => wp_create_nonce('itsec_jquery_filetree'))); wp_register_style('itsec_jquery_filetree_style', $this->module_path . 'filetree/jqueryFileTree.css', array(), $itsec_globals['plugin_build']); //add multi-select css wp_enqueue_style('itsec_jquery_filetree_style'); wp_register_style('itsec_file_change_css', $this->module_path . 'css/admin-file-change.css', array(), $itsec_globals['plugin_build']); //add multi-select css wp_enqueue_style('itsec_file_change_css'); } }
/** * 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'; } }
/** * Gets file list for tree. * * Processes the ajax request for retreiving the list of files and folders that can later either * excluded or included. * * @since 4.0.0 * * @return void */ public function wp_ajax_itsec_jquery_filetree_ajax() { global $itsec_globals; if (!wp_verify_nonce(sanitize_text_field($_POST['nonce']), 'itsec_jquery_filetree') || !current_user_can($itsec_globals['plugin_access_lvl'])) { die(__('Security error!', 'better-wp-security')); } $directory = sanitize_text_field($_POST['dir']); $directory = urldecode($directory); $directory = realpath($directory); $base_directory = realpath(ITSEC_Lib::get_home_path()); // Ensure that requests cannot traverse arbitrary directories. if (0 !== strpos($directory, $base_directory)) { $directory = $base_directory; } $directory .= '/'; if (file_exists($directory)) { $files = scandir($directory); natcasesort($files); if (2 < count($files)) { /* The 2 accounts for . and .. */ echo "<ul class=\"jqueryFileTree\" style=\"display: none;\">"; //two loops keep directories sorted before files // All files and directories (alphabetical sorting) foreach ($files as $file) { if ('.' != $file && '..' != $file && file_exists($directory . $file) && is_dir($directory . $file)) { echo '<li class="directory collapsed"><a href="#" rel="' . htmlentities($directory . $file) . '/">' . htmlentities($file) . '<div class="itsec_treeselect_control"><img src="' . plugins_url('images/redminus.png', __FILE__) . '" style="vertical-align: -3px;" title="Add to exclusions..." class="itsec_filetree_exclude"></div></a></li>'; } elseif ('.' != $file && '..' != $file && file_exists($directory . $file) && !is_dir($directory . $file)) { $ext = preg_replace('/^.*\\./', '', $file); echo '<li class="file ext_' . $ext . '"><a href="#" rel="' . htmlentities($directory . $file) . '">' . htmlentities($file) . '<div class="itsec_treeselect_control"><img src="' . plugins_url('images/redminus.png', __FILE__) . '" style="vertical-align: -3px;" title="Add to exclusions..." class="itsec_filetree_exclude"></div></a></li>'; } } echo "</ul>"; } } exit; }
/** * Scans all files in a given path * * @since 4.0 * * @param string $path [optional] path to scan, defaults to WordPress root * @param bool $scheduled_call is this a scheduled call * @param mixed $chunk the current chunk or false * * @return array array of files found and their information * */ private function scan_files($path = '', $scheduled_call, $chunk) { if ($chunk !== false) { $content_dir = explode('/', WP_CONTENT_DIR); $plugin_dir = explode('/', WP_PLUGIN_DIR); $dirs = array('wp-admin/', 'wp-includes/', $content_dir[sizeof($content_dir) - 1] . '/', $content_dir[sizeof($content_dir) - 1] . '/uploads/', $content_dir[sizeof($content_dir) - 1] . '/themes/', $content_dir[sizeof($content_dir) - 1] . '/' . $plugin_dir[sizeof($plugin_dir) - 1] . '/', ''); $path = $dirs[$chunk]; unset($dirs[$chunk]); $this->excludes = $dirs; } $time_offset = get_option('gmt_offset') * 60 * 60; $data = array(); $clean_path = sanitize_text_field($path); if ($directory_handle = opendir(ITSEC_Lib::get_home_path() . $clean_path)) { //get the directory while (($item = readdir($directory_handle)) !== false) { // loop through dirs if ($item != '.' && $item != '..') { //don't scan parent/etc $relname = $path . $item; $absname = ITSEC_Lib::get_home_path() . $relname; if (is_dir($absname) && filetype($absname) == 'dir') { $is_dir = true; $check_name = trailingslashit($relname); } else { $is_dir = false; $check_name = $relname; } if ($this->is_checkable_file($check_name) === true) { //make sure the user wants this file scanned if ($is_dir === true) { //if directory scan it $data = array_merge($data, $this->scan_files($relname . '/', $scheduled_call, false)); } else { //is file so add to array $data[$relname] = array(); $data[$relname]['d'] = @filemtime($absname); $data[$relname]['h'] = @md5_file($absname); } } } } @closedir($directory_handle); //close the directory we're working with } return $data; // return the files we found in this dir }
/** * Sanitize and validate input * * @since 1.6 * * @param Array $input array of input fields * * @return Array Sanitized array */ public function sanitize_module_input($input) { $input['enabled'] = isset($input['enabled']) && intval($input['enabled'] == 1) ? true : false; $input['standard'] = isset($input['standard']) && intval($input['standard'] == 1) ? true : false; $input['standard_interval'] = isset($input['standard_interval']) ? absint($input['standard_interval']) : 5; //Build an array of items for individual scan if (isset($input['individual'])) { foreach ($input['individual'] as $index => $item) { if (strlen(sanitize_text_field($input['individual'][$index]['resource'])) > 0) { $input['individual'][$index]['type'] = isset($item['type']) && $item['type'] == 1 ? 1 : 0; $input['individual'][$index]['resource'] = sanitize_text_field($input['individual'][$index]['resource']); if ($input['individual'][$index]['type'] === 1) { if (file_exists(trailingslashit(ITSEC_Lib::get_home_path()) . $input['individual'][$index]['resource']) !== true) { $input['enabled'] = false; $type = 'error'; $message = sprintf('%s <strong>%s</strong> %s<br />', __('The resource ', 'it-l10n-ithemes-security-pro'), sanitize_text_field($input['individual'][$index]['resource']), __('is not valid. Please try again.', 'it-l10n-ithemes-security-pro')); add_settings_error('itsec', esc_attr('settings_updated'), $message, $type); } } else { if (ITSEC_Lib::validate_url($input['individual'][$index]['resource']) != true) { $input['enabled'] = false; $type = 'error'; $message = sprintf('%s <strong>%s</strong> %s<br />', __('The resource ', 'it-l10n-ithemes-security-pro'), sanitize_text_field($input['individual'][$index]['resource']), __('is not valid. Please try again.', 'it-l10n-ithemes-security-pro')); add_settings_error('itsec', esc_attr('settings_updated'), $message, $type); } } } else { unset($input['individual'][$index]); } } } else { $input['individual'] = array(); } //Clean out extras from last scans if ($input['enabled'] === true) { $last_scans = get_site_option('itsec_malware_scheduling_last_scans'); if (is_array($last_scans) && sizeof($last_scans) > 0 && is_array($input['individual']) && sizeof($input['individual']) > 0) { foreach ($last_scans as $resource => $scan) { $found = false; //Assume we're no longer scheduling a scan for the item previously scanned if ($resource === 'standard' || $resource === 'overall') { $found = true; //Overall and standard last scans should always be true } if ($found === false) { foreach ($input['individual'] as $item) { if ($resource == $item['resource']) { $found = true; } } if ($found === false) { unset($last_scans[$resource]); //Remove the resource from last scans if not found } } } update_site_option('itsec_malware_scheduling_last_scans', $last_scans); } } else { delete_site_option('itsec_malware_scheduling_last_scans'); //If scanned malware scheduling isn't enabled delete the "last scans" data from the options table } if (is_multisite()) { $this->core->show_network_admin_notice(false); $this->settings = $input; } return $input; }