Scan a Linux server for malware (and what scanners miss)

Updated November 2026

Malware scanners find known bad files quickly, which makes them a good first check after a suspected compromise. A clean scan does not prove a server is clean, though: rootkits (malware that hides itself from normal tools) can hide from the scanner, and many intrusions use no malware at all. Combine a scan with package verification and a manual check for backdoors.

Do this first.

  1. If you suspect a compromise, copy logs and suspicious files somewhere safe before scanning; some scanners can move or delete what they flag.
  2. Never let a scanner delete files automatically on a production server. Use report-only or quarantine mode.
  3. If the attacker had root, scan from rescue media with the disk mounted read-only, because tools on the running system may be lying to you.

Which tool finds what

Linux malware scanners at a glance
ToolGood atInstall
ClamAVKnown malware files of all kinds, mail and uploadsDebian/Ubuntu repositories; EPEL on RHEL-family
Linux Malware Detect (LMD)PHP web shells and injected code on web and shared hosting serversFrom the rfxn project (GitHub)
rkhunterKnown rootkit files, changed system binaries, hidden files, suspicious settingsDebian/Ubuntu repositories; EPEL
chkrootkitSigns of known rootkits, worms and kernel-module trojansDebian/Ubuntu repositories
YARAYour own or vendor-published rules for a specific threatDebian/Ubuntu repositories; EPEL
debsums, dpkg -V, rpm -VaSystem files that differ from what the package installedBuilt in (debsums is a separate package)

ClamAV

# Debian/Ubuntu: the clamav-freshclam service keeps signatures updated
sudo apt install clamav clamav-daemon
systemctl status clamav-freshclam

# RHEL-family (enable EPEL first; on AlmaLinux and Rocky: sudo dnf install epel-release)
sudo dnf install clamav clamd clamav-update
sudo freshclam

Scan the places malware usually lands, report only infected files, and keep a log. nice and ionice keep the scan from slowing a busy server:

sudo nice -n 19 ionice -c3 clamscan --recursive --infected \
  --log=/root/clamscan-$(date +%F).log \
  /home /root /tmp /var/tmp /dev/shm /var/www /etc /usr/local

To quarantine instead of just report, add --move=/root/quarantine. The ClamAV manual calls --remove “generally a terrible idea” outside upload directories, because false positives happen. Note that --max-filesize skips larger files and treats them as clean.

Linux Malware Detect

LMD (also called maldet) is designed for threats on shared hosting servers: web shells, injected backdoors and obfuscated PHP. It uses ClamAV as its scan engine when ClamAV is installed. Install it from the project’s repository:

git clone https://github.com/rfxn/linux-malware-detect.git
cd linux-malware-detect
sudo ./install.sh

sudo maldet -u                        # update signatures
sudo maldet -a /var/www               # scan everything under /var/www
sudo maldet -r /var/www 7             # only files changed in the last 7 days
sudo maldet -e list                   # list scan reports
sudo maldet -e SCANID                 # view one report
sudo maldet -q SCANID                 # quarantine the hits from that scan

By default quarantine_hits=0 in /usr/local/maldetect/conf.maldet, so LMD only reports. Leave it that way until you have reviewed a few reports.

rkhunter and chkrootkit

# Debian/Ubuntu
sudo apt install rkhunter chkrootkit
# RHEL-family (EPEL)
sudo dnf install rkhunter

sudo rkhunter --check --sk --rwo      # run all checks, no prompts, warnings only
sudo chkrootkit -q                    # quiet: only report suspicious findings

Both tools produce false positives; Debian’s rkhunter notes list, for example, hidden directories created by udev and Java. Investigate each warning rather than ignoring the whole report.

YARA rules

YARA matches files against patterns you describe. It is most useful when a security vendor or CERT publishes rules for a specific threat, such as the rule Trend Micro published for the Kinsing ActiveMQ exploit. A minimal example that flags a common web shell pattern:

cat > php-eval.yar <<'EOF'
rule php_eval_base64
{
    strings:
        $a = "eval(base64_decode(" nocase
    condition:
        $a
}
EOF

sudo apt install yara                 # Debian/Ubuntu; EPEL on RHEL-family
sudo yara -r -s php-eval.yar /var/www

-r scans recursively (and follows symlinks) and -s prints the matching strings. Only use rules from sources you trust.

Verify installed packages

Package managers know the checksum of every file they installed. Changed system binaries are a strong sign of tampering.

# Debian/Ubuntu
sudo dpkg --verify                    # all packages; "??5??????" means contents changed
sudo apt install debsums
sudo debsums -s                       # report only errors
sudo debsums -ca                      # changed files, including config files

# RHEL, AlmaLinux, Rocky, Fedora
sudo rpm -Va

In rpm -Va output, 5 means the file contents differ, S the size, M the permissions, and U/G the owner; a c marks a configuration file, which you would expect to change. A changed /usr/bin/ps, /usr/sbin/sshd or PAM module is serious; a changed /etc/ssh/sshd_config may just be your own edit.

The dpkg manual is clear that this is “only an integrity check and should not be considered as any kind of security verification”: an attacker with root can also change the stored checksums. To reinstall Debian packages whose files changed, the debsums manual gives this command (shown here with sudo added inside, so debsums can read every file):

sudo apt-get install --reinstall $(dpkg -S $(sudo debsums -c) | cut -d : -f 1 | sort -u)

What scanners miss

Scan from rescue media

When root was compromised, boot the server from your provider’s rescue system or a live image, mount the disk read-only, and scan it from there:

lsblk                                 # find the server's root partition
sudo mkdir -p /mnt/suspect
sudo mount -o ro /dev/sda1 /mnt/suspect
sudo clamscan --recursive --infected /mnt/suspect
sudo chkrootkit -r /mnt/suspect

When to call a professional

If scans flag system binaries, kernel modules or PAM files, or a scanner reports a rootkit, treat the server as fully compromised: plan a rebuild and get help from your host or an incident responder. Scanners are for triage, not proof of a clean system.

Sources