In short: On Linux, you find changed files with find and a time window, for example from 17 October 2026, the first attack attempt on PHP2Shell observed according to media reports. Check not only the content modification time (mtime) but also that of the metadata (ctime), because the former is easy to forge. The result becomes reliable only through comparison with package checksums, Git or a backup.
Why timestamps are a good starting point, but not proof
Anyone who brings code onto a server changes files. New webshells, modified configuration files, added lines in existing scripts: all of this leaves timestamps. Searching for changes in the right time window is therefore one of the fastest routes to first findings.
For PHP2Shell, 17 October 2026 is a good start of the window, the day of the first observed attack attempt according to media reports. The patches appeared on 21 October. Anyone who updated their server only afterward searches up to the day of their own update and beyond. How to recognize webshells among the findings is described in Recognizing and removing webshells. This article is about the search method itself.
The three timestamps of a file
Linux stores several points in time for every file. Two are decisive for searching for changes.
| Timestamp | Meaning | Forgeable? |
|---|---|---|
| mtime | last change of the content | yes, e.g. with touch, by anyone who may write the file |
| ctime | last change of content or metadata such as permissions | not with simple means |
| atime | last read access | often disabled or imprecise, of little use for the search |
Attackers like to backdate the mtime to the date of neighboring files so that a new file does not stand out. The ctime changes along with it, though. A file with an old mtime and a fresh ctime is therefore a strong indication of manipulation.
Watch time zones when comparing. find and ls show the server's local time, whereas many log files and services work in UTC. Anyone who lays findings from the file system and logs side by side should convert all details to the same time zone, otherwise events seem not to fit together. The patches appeared at about 14:00 UTC on 21 October, that is, at 16:00 German time.
Finding changed files on Linux with find
All commands only read. Adjust the path and date.
# Content changed since 17 Oct 2026, sorted, with mtime, ctime and owner
find /var/www -type f -newermt "2026-10-17" -printf '%TY-%Tm-%Td %TH:%TM %CY-%Cm-%Cd %CH:%CM %u %p\n' | sort
# Metadata changed since 17 Oct 2026 (also finds backdated files)
find /var/www -type f -newerct "2026-10-17" -printf '%C+ %T+ %p\n' | sort
# Filter out known noise: cache, logs, sessions
find /var/www -type f -newerct "2026-10-17" \
-not -path "*/cache/*" -not -path "*/logs/*" -not -path "*/sessions/*" -printf '%C+ %p\n' | sort
# Also look outside the web directory
find /etc /usr/local/bin /tmp /var/tmp /dev/shm -xdev -type f -newerct "2026-10-17" -printf '%C+ %p\n' 2>/dev/null | sort
For every hit, compare both timestamps. If the ctime is clearly younger than the mtime, and nobody changed permissions or copied files in that time, the file belongs on the list. Also watch the owner: a file of the web server user among files of the deploy user stands out.
Do not forget hidden files and directories. Names that begin with a dot are not shown by many file managers or by a plain ls. Attackers like to use that, as well as names that are confusingly similar to real files.
# Hidden files and folders in the web directory, excluding known ones such as .htaccess and .git
find /var/www -name ".*" -not -name ".htaccess" -not -name ".well-known" -not -path "*/.git/*" -printf '%C+ %u %p\n' | sort
Compare against a trustworthy source
Timestamps show where something has moved. Whether it was a legitimate change is shown only by comparison with a source you trust.
- Package manager: For system files,
dpkg --verify(Debian/Ubuntu) orrpm -Va(RHEL family) check the files against the checksums of the installed packages. Configuration files legitimately deviate, program files do not. - Git: If the application is in a repository,
git -C /var/www/projekt status --porcelainshows every deviation from the last commit. - CMS checksums: Many systems can compare their core files against the official checksums, see Comparing CMS core files with the original.
- Backup from before the incident: A comparison as a dry run lists differences without copying anything.
# Only list differences between the backup state and the live system (dry run, copies nothing)
rsync -rcn --out-format="%n" /backup/www-2026-10-15/ /var/www/
The backup comparison presupposes that the backup was made before the incident and was not itself altered. Why separately stored backups are decisive here is explained in Backups under the 3-2-1 rule.
Save the results of every search with the date in a file outside the server. These lists later become the incident timeline, and they document what you checked and when.
When there is neither a backup nor a repository
With many smaller websites there is no clean basis for comparison: no Git, no backup from before the incident, plugins updated by hand for years. You are still not entirely without a reference point.
Download the CMS and the extensions in exactly the installed versions from the vendor and compare these files with the server. Whatever differs or is missing there deserves a look. What remains are your own customizations, uploads and configuration; there the timestamp search helps, supplemented by a look at owner and permissions. Files that are the only ones in a directory with a different group, different permissions or a clearly younger ctime than their neighbors belong on the list.
Honestly: without a basis for comparison, some residual uncertainty remains. For systems with sensitive data, a rebuild from clean sources is then often more reliable than searching for each individual changed file. For the future the lesson is simple: a repository for the code and regular, separately stored backups.
Typical sources of error in the search
- Exclusions too generous: Cache and upload folders are popular hiding places.
- Only mtime checked: Backdated files slip through.
- Deployment within the time window: A regular rollout changes hundreds of files and hides individual findings. Compare against the repository.
- Files already opened or copied: Copies that do not preserve timestamps destroy traces. Secure with tools that preserve timestamps.
- Only the web directory searched: Attackers also place tools in
/tmp,/dev/shmor in the web server user's home directory. - Permission changes overlooked: A file whose permissions suddenly allow write access for everyone is a finding, even if its content is unchanged.
How findings are put together into a sequence is shown in Building the timeline of an incident.
How does PHP SOS help?
- Search systematically: We search web directories and system paths for changes in the relevant time window and evaluate mtime and ctime together.
- Check against originals: We compare against packages, repository, CMS checksums and your backups.
- Assess findings: We separate regular changes from manipulation and secure evidence.
- Clean up: With malware removal, we restore a clean state and document it.
Frequently asked questions
How do I find all files changed since a certain date?
With find and the -newermt option, for example find /var/www -type f -newermt "2026-10-17". For changes to metadata, use -newerct. Both commands only read and change nothing.
What is the difference between mtime and ctime?
mtime is the time of the last content change and can be backdated with simple means. ctime is the time of the last change to content or metadata and cannot be forged as easily. If the two differ greatly, a close look is worthwhile.
How do I exclude cache files from the search?
With -not -path for known cache, log and session folders. But do not exclude too generously, because attackers like to place files exactly where many changes are normal.
Which check is the most reliable?
Comparison against a trustworthy source: checksums from the package manager, a Git repository or a backup from before the incident. Timestamps are a good starting point but not proof.