# Comparing CMS Core Files With the Original

> Compare CMS core files with the original: checksums, a clean reference state and diff explained for WordPress, Composer projects and system packages.

Source: https://phpsos.de/en/blog/cms-kerndateien-vergleichen/  
As of: 25/10/2026  
Provider: PHP SOS, PHP emergency help and server security. Immediate help via WhatsApp: https://wa.me/491736494914?text=Hello%20PHP%20SOS%2C%20we%20need%20help%20with%20our%20PHP%20server.%20Company%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**In short:** To check CMS core files, compare the installed files with a clean original of the same version: for WordPress via the official checksums, for other systems via a fresh download or a rebuild from composer.lock. Every deviation is something to examine. The comparison also finds unknown malicious code, but covers only files for which an original exists.

## Why the comparison finds more than any signature

Malware scanners look for known patterns. What they do not know, they miss. A comparison with the original works the other way round: it does not ask whether a file looks suspicious, but whether it matches exactly what the vendor shipped. Every deviation stands out, whether or not it follows a known pattern.

This is especially valuable after PHP2Shell. For the vulnerabilities CVE-2026-109618 and CVE-2026-109619 there are no published, confirmed indicators of compromise. Scanners therefore cannot search specifically for PHP2Shell traces. A comparison with the original, by contrast, finds every change to the core, regardless of how it came about. Why scanners alone are not enough is explained in the article [Malware scanners for websites: what they find and what they don't](https://phpsos.de/en/blog/grenzen-von-malware-scannern/).

## The principle: same version, clean source

A comparison is only as good as its reference. Three conditions must be met:

1. **Exactly the same version:** A comparison against a newer version shows hundreds of harmless differences. Determine the installed version from the application or the `composer.lock`.
2. **Official source:** The original comes from the vendor, from the official package directory or from your own version control system. Not from an old backup of the affected server.
3. **Comparison on a copy:** Work on a secured copy of the web directory so that timestamps and traces are preserved.

| System | Reference | Tool |
|---|---|---|
| WordPress core and plugins from the directory | checksums from WordPress.org | `wp core verify-checksums`, `wp plugin verify-checksums` |
| Composer projects (e.g. Shopware 6, Laravel, Symfony, Drupal, TYPO3 in Composer mode) | rebuild from `composer.lock` | `composer install` in an empty directory, then `diff` |
| CMS with a download package | package of the same version from the vendor | `diff -rq` |
| Own projects with Git | last known commit | `git status`, `git diff` |
| System packages of the server | package database of the distribution | `dpkg --verify`, `rpm -Va` |

## WordPress: more than verify-checksums

How to check core and plugins with WP-CLI is described in the guide [Finding backdoors in WordPress](https://phpsos.de/en/ratgeber/backdoor-wordpress-finden/). One addition is worthwhile: according to the WP-CLI documentation, the option `--include-root` checks all files and folders in the root directory and warns about entries that do not belong to WordPress. Attackers like to place files there whose names resemble core files.

```bash
# Core against official checksums, including foreign files in the root directory
wp core verify-checksums --include-root
```

This route does not cover commercial plugins and themes. For them, download the original package of the same version from the vendor and compare with `diff`.

## Checking CMS core files in Composer projects

Many modern PHP applications consist largely of packages installed by Composer, the package manager for PHP. How it works is explained on the page [Composer: the package manager for PHP](https://phpsos.de/en/php/composer/). The file `composer.lock` records exactly which versions are installed. According to the Composer documentation, `composer install` uses these exact versions. This allows the delivered state to be rebuilt:

```bash
# On a clean system, not on the affected server
mkdir /tmp/referenz && cd /tmp/referenz
cp /pfad/zur/kopie/composer.json /pfad/zur/kopie/composer.lock .
composer install --no-scripts --no-plugins --no-autoloader

# List differences in the vendor folder
diff -rq /tmp/referenz/vendor /pfad/zur/kopie/vendor
```

The options `--no-scripts` and `--no-plugins` prevent scripts from the packages from being executed during the rebuild. If production was installed with `--no-dev`, use this option for the rebuild too, otherwise development packages show up as a difference. Watch for two kinds of results: files that differ, and files that exist only on the server. The second group is often the more interesting one. How to additionally check the installed packages for known vulnerabilities is described in the guide [Checking Composer dependencies for vulnerabilities](https://phpsos.de/en/ratgeber/composer-abhaengigkeiten-pruefen/).

## Compare the operating system too

If an attacker had root rights, they may also have replaced system programs. The package managers come with their own comparison:

```bash
# Debian, Ubuntu: files whose content differs from the package
sudo dpkg --verify

# RHEL, AlmaLinux, Rocky: check all packages
sudo rpm -Va
```

A `5` in the third position of the output means that the content of a file has changed. According to the dpkg manual, the content comparison is currently the only effective check there. Changed configuration files are normal and marked with `c`. A modified program in `/usr/bin`, however, is a serious alarm sign. Note: an attacker with root rights can also manipulate the package database. If root access is suspected, a rebuild is more reliable than any comparison.

> **Tip:**
> A version control system for the application code turns future comparisons into a matter of seconds. `git status` then shows every deviation from the approved state.

## Assessing deviations and knowing the limits

Not every deviation is an attack. Some agencies used to modify core files directly instead of using extensions. Language packs, line endings after a transfer via FTP, or fixes applied afterwards also produce differences. What matters is whether someone can explain the change.

Go through each deviation individually and note the result: known and documented, harmlessly explainable, or unclear. Open unclear files only as text on a copy, and replace them from the clean source. For files that exist only on the server, the question is simpler: if nobody knows them, they should be secured and removed after their content has been checked.

Uploads, configuration files such as `wp-config.php` or `.env`, custom modifications and caches have no original. They must be checked specifically, as must the database, cron jobs, user accounts and SSH keys. A clean comparison is therefore an important building block, but not an acquittal for the whole server.

## How does PHP SOS help?

- We determine the installed versions and build a clean reference from official sources.
- We compare core, extensions, Composer packages and system programs and assess every deviation.
- We check the areas without an original specifically and replace modified files from a clean source as part of [malware removal](https://phpsos.de/en/leistungen/malware-entfernung/).
- On request, we set up a version state against which future checks run.


## Frequently asked questions

**How do I check whether WordPress core files have been modified?**  
With WP-CLI and the command wp core verify-checksums. It compares the files with the checksums that WordPress.org publishes for the installed version. With the option --include-root, WP-CLI also warns about files in the root directory that do not belong to WordPress.

**What do I do with a CMS that has no built-in check?**  
You download exactly the same version from the vendor's official source and compare both directories with diff. For Composer projects, you rebuild the state from composer.lock in an empty directory and compare the vendor folder.

**Does the comparison also find malicious code in plugins and themes?**  
Only if a clean original exists for them, for example from the official directory or from the vendor. Custom modifications, uploads and configuration files have no original and must be checked separately.

**Does the comparison replace a malware scanner?**  
It complements it. The comparison finds every change to known files, including unknown malicious code. But it says nothing about files without an original, the database, cron jobs or accounts.

## Sources

- [WordPress](https://wordpress.org/)
- [Composer](https://getcomposer.org/)
- [Debian Security Tracker](https://security-tracker.debian.org/)
