Example #1
0
/**
 * 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;
}