/** * Check whether the core WordPress files where modified, removed or if any file * was added to the core folders. This function returns an associative array with * these keys: * * <ul> * <li>modified: Files with a different checksum according to the official files of the WordPress version filtered,</li> * <li>stable: Files with the same checksums than the official files,</li> * <li>removed: Official files which are not present in the local project,</li> * <li>added: Files present in the local project but not in the official WordPress packages.</li> * </ul> * * @param integer $version Valid version number of the WordPress project. * @return array Associative array with these keys: modified, stable, removed, added. */ function sucuriscan_check_core_integrity($version = 0) { $latest_hashes = SucuriScanAPI::get_official_checksums($version); $base_content_dir = defined('WP_CONTENT_DIR') ? basename(rtrim(WP_CONTENT_DIR, '/')) : ''; if (!$latest_hashes) { return false; } $output = array('added' => array(), 'removed' => array(), 'modified' => array(), 'stable' => array()); // Get current filesystem tree. $wp_top_hashes = sucuriscan_get_integrity_tree(ABSPATH, false); $wp_admin_hashes = sucuriscan_get_integrity_tree(ABSPATH . 'wp-admin', true); $wp_includes_hashes = sucuriscan_get_integrity_tree(ABSPATH . 'wp-includes', true); $wp_core_hashes = array_merge($wp_top_hashes, $wp_admin_hashes, $wp_includes_hashes); // Compare remote and local checksums and search removed files. foreach ($latest_hashes as $file_path => $remote_checksum) { if (sucuriscan_ignore_integrity_filepath($file_path)) { continue; } $full_filepath = sprintf('%s/%s', ABSPATH, $file_path); // Patch for custom content directory path. if (!file_exists($full_filepath) && strpos($file_path, 'wp-content') !== false && defined('WP_CONTENT_DIR')) { $file_path = str_replace('wp-content', $base_content_dir, $file_path); $dir_content_dir = dirname(rtrim(WP_CONTENT_DIR, '/')); $full_filepath = sprintf('%s/%s', $dir_content_dir, $file_path); } // Check whether the official file exists or not. if (file_exists($full_filepath)) { $local_checksum = @md5_file($full_filepath); if ($local_checksum !== false && $local_checksum === $remote_checksum) { $output['stable'][] = array('filepath' => $file_path, 'is_fixable' => false, 'modified_at' => 0); } else { $modified_at = @filemtime($full_filepath); $is_fixable = (bool) is_writable($full_filepath); $output['modified'][] = array('filepath' => $file_path, 'is_fixable' => $is_fixable, 'modified_at' => $modified_at); } } else { $is_fixable = is_writable(dirname($full_filepath)); $output['removed'][] = array('filepath' => $file_path, 'is_fixable' => $is_fixable, 'modified_at' => 0); } } // Search added files (files not common in a normal wordpress installation). foreach ($wp_core_hashes as $file_path => $extra_info) { $file_path = str_replace(DIRECTORY_SEPARATOR, '/', $file_path); $file_path = preg_replace('/^\\.\\/(.*)/', '$1', $file_path); if (sucuriscan_ignore_integrity_filepath($file_path)) { continue; } if (!array_key_exists($file_path, $latest_hashes)) { $full_filepath = ABSPATH . '/' . $file_path; $modified_at = @filemtime($full_filepath); $is_fixable = (bool) is_writable($full_filepath); $output['added'][] = array('filepath' => $file_path, 'is_fixable' => $is_fixable, 'modified_at' => $modified_at); } } return $output; }