Home / Alt manpages / chkrootkit-daily(8)

  • chkrootkit-daily(8)
  • Admin command
  • linux

Tune chkrootkit-daily Reports Without Hiding Alerts

A daily rootkit report nobody reads is worse than none, and a report filtered until it is silent is worse still. This guide sets up Debian's chkrootkit-daily job, builds a known-good baseline and shows you when a later report needs investigating. It uses chkrootkit 0.58b-1, with the scanner reporting version 0.58b, and takes about 20 minutes for the first run and baseline review.

  • You need: a shell and a user who can use sudo. The daily job itself normally runs with elevated privileges from its timer or cron.
  • What it is not. This is a local rootkit check, not proof a machine is clean. It can report false positives, and an attacker with control of the host may be able to interfere with local tools or their output.
  • Keep the raw report. Investigate unexpected changes separately.

1. Confirm the installed command and scheduler

Start with read-only checks. They do not need sudo:

$ command -v chkrootkit-daily
/usr/sbin/chkrootkit-daily
$ dpkg-query -W -f='\${Package} \${Version}\n' chkrootkit
chkrootkit 0.58b-1
$ chkrootkit -V
chkrootkit version 0.58b
$ systemctl list-timers --all 'chkrootkit*' --no-pager

The manual describes chkrootkit-daily as suitable for a systemd timer or a cron job. On a systemd host, the last command should show chkrootkit.timer if the packaged timer is installed. Do not enable a second scheduler just because one command printed nothing: check your distribution's package files and existing cron configuration first.

Checkpoint

You know which package and scheduler are present. If the binary or timer is missing, stop and use your normal package-management process rather than copying a script from elsewhere.

2. Read the configuration before changing it

The configuration file is /etc/chkrootkit/chkrootkit.conf. The daily script sources it as shell code, so it must stay valid shell syntax and be owned and writable only by trusted administrators. Read it without changing anything:

$ sudo sed -n '1,220p' /etc/chkrootkit/chkrootkit.conf
$ sudo test -r /etc/chkrootkit/chkrootkit.ignore && sudo sed -n '1,120p' /etc/chkrootkit/chkrootkit.ignore || echo 'no ignore file'

The settings that matter are RUN_DAILY, RUN_DAILY_OPTS, DIFF_MODE, FILTER, IGNORE_FILE and MAILTO. The packaged defaults:

  • Enable the daily run.
  • Pass no scanner options.
  • Compare output with an expected file.
  • Normalise changing process identifiers and network-manager messages.
  • Send the report to root.

Your installed file is authoritative if it differs from those defaults.

Warning

Do not treat FILTER or the ignore file as a way to make an alert disappear. A filter can rewrite output, and each line in IGNORE_FILE is an extended regular expression that removes matching lines. Every removed line is evidence you will no longer see.

3. Choose reporting and email deliberately

Decide where the report should arrive before you edit anything. This is a persistent, security-sensitive change. Make a backup first, then use an editor that preserves the file's ownership and permissions:

$ sudo cp -a /etc/chkrootkit/chkrootkit.conf /etc/chkrootkit/chkrootkit.conf.bak
$ sudoedit /etc/chkrootkit/chkrootkit.conf
  • Leave RUN_DAILY_OPTS="" at first. The report then contains all scanner output.
  • Keep DIFF_MODE="true" if you want routine output compared with a baseline.
  • Set MAILTO="[email protected]" to a local address or account your mail system can deliver to. If MAILTO is empty, output stays on standard output, which normally means the systemd journal or a cron-generated message.
  • For the full filtered report every day, set DIFF_MODE="false". In that mode RUN_DAILY_OPTS="-q" can reduce noise, but quiet mode suppresses tests that find nothing suspicious, so do not add -q merely to shorten the email.

Check the edited file before running it:

$ sudo sh -n /etc/chkrootkit/chkrootkit.conf
$ sudo grep -E '^(RUN_DAILY|RUN_DAILY_OPTS|DIFF_MODE|IGNORE_FILE|MAILTO)=' /etc/chkrootkit/chkrootkit.conf

Recovery

A non-zero result from sh -n means the daily job may fail before scanning. Undo the edit with sudo cp -a /etc/chkrootkit/chkrootkit.conf.bak /etc/chkrootkit/chkrootkit.conf.

4. Run the first scheduled scan

The daily command writes under /var/log/chkrootkit, so this step needs elevated privileges and changes host state. It can take a little while, and you should not run it at the same time as the timer:

$ systemctl list-timers --all 'chkrootkit*' --no-pager
$ sudo systemctl start chkrootkit.service
$ sudo systemctl status --no-pager chkrootkit.service

The service should finish without an active process left behind. A successful service run is not the same as a clean scan, so inspect the report and the files it creates:

$ sudo ls -l /var/log/chkrootkit/
$ sudo sed -n '1,160p' /var/log/chkrootkit/chkrootkit-daily.log
$ sudo sed -n '1,160p' /var/log/chkrootkit/log.today
$ sudo sed -n '1,80p' /var/log/chkrootkit/log.today.raw

Which file is which:

  • log.today.raw holds the raw scanner output.
  • log.today is that output after FILTER and IGNORE_FILE have been applied.
  • chkrootkit-daily.log holds the wrapper's own messages and the final report.

Variable process IDs and normal network-manager notices are why the default filter exists. A line containing INFECTED, an unexpected binary or an unfamiliar process is a reason to investigate, not a reason to add a new ignore pattern.

5. Create and review the expected baseline

With diff mode enabled, the first run tells you that /var/log/chkrootkit/log.expected does not exist. Review log.today and the raw file first, and only set a baseline when you understand every remaining line:

$ sudo diff -u /var/log/chkrootkit/log.today /var/log/chkrootkit/log.today.raw || true
$ sudo cp -a /var/log/chkrootkit/log.today /var/log/chkrootkit/log.expected

The first command may show differences, because filtering is expected. The second is an elevated, persistent change that replaces any existing expected file, so back that up first if one exists:

$ sudo test -f /var/log/chkrootkit/log.expected && sudo cp -a /var/log/chkrootkit/log.expected /var/log/chkrootkit/log.expected.bak
$ sudo cp -a /var/log/chkrootkit/log.today /var/log/chkrootkit/log.expected

On a later run, unchanged filtered output produces no alert text. A changed report prints a unified diff between log.expected and log.today. Compare the change with the raw output before you edit the baseline.

Recovery

To undo a baseline update, restore log.expected.bak. If it was a new file, remove only that file, and only after checking that no current investigation needs it.

6. Use scanner options sparingly

chkrootkit supports these options, and the daily wrapper passes RUN_DAILY_OPTS to the scanner:

  • -q for quiet output.
  • -x for expert detail.
  • -d for debug output.
  • -e for named exclusions.
  • -s for sniffer-test exclusions.
  • -n to ignore NFS directories.
  • -l to list tests.

Options cannot be combined, so write -q -n, not -qn.

Use exclusions only when you have recorded why a result is a known false positive. A standard network manager showing up in the sniffer test is the classic case. Prefer the documented -s regular expression or a narrow ignore pattern, and keep the raw report so the original evidence survives.

Warning

Never use -r or -p in the daily job without testing the alternate root or trusted command path separately.

Done means

  • The setup is confirmed. You know the installed package and scheduler.
  • The config parses. /etc/chkrootkit/chkrootkit.conf passes shell syntax checking.
  • Reports arrive. They reach the intended local address, or are available in the journal or cron mail.
  • All three logs were read. That means log.today.raw, log.today and chkrootkit-daily.log.
  • The baseline was reviewed first. The expected file was created only after its contents were checked.
  • Findings come from the raw report. Unexpected results are investigated, not hidden with filters or ignores.