Chkrootkit has a simple way to “set and forget” the system, only notifying you of when it sees something new.
Note
For how to install it, see Checking for Rootkits with chkrootkit.
However, what about if there’s a changing PID or other detail in the output that changes with every boot? Or if there are network interfaces that change on each boot?
We don’t want these alerts, and here we’ll show how to exclude them.
What False Positives look like
Here’s an example of how these false positives look like and how to read them. You may skip to the next section if you already know this.
You’ve likely already done this, but if not, run the cronjob:
/etc/cron.daily/chkrootkit
It may show something changed, but you’ll see it’s only the PIDs. It shows as a normal diff
format, was was added (+
), and what was removed (-
).
chkrootkit output was not as expected.
The difference is:
--- [ BEGIN: diff -u /var/log/chkrootkit/log.expected /var/log/chkrootkit/log.today ] ---
--- /var/log/chkrootkit/log.expected
+++ /var/log/chkrootkit/log.today
@@ -195,8 +195,8 @@
-eth0: PACKET SNIFFER(/usr/lib/systemd/systemd-networkd[717])
-eth0: PACKET SNIFFER(/usr/lib/systemd/systemd-networkd[717])
+eth0: PACKET SNIFFER(/usr/lib/systemd/systemd-networkd[726])
+eth0: PACKET SNIFFER(/usr/lib/systemd/systemd-networkd[726])
--- [ END: diff -u /var/log/chkrootkit/log.expected /var/log/chkrootkit/log.today ] ---
As you can see, only the PID of the process changed from 717 ti 726, due to the machine rebooting.
If you’re using Docker, you may see the br
interfaces changing:
+br-a7b7812cce5f: not promisc and no packet sniffer sockets
-br-b12cd3fa2c4e: not promisc and no packet sniffer sockets
How to Exclude
There are two ways to exclude this, via the Filter
or the Ignore
file.
Tip
Only use filter or ignore for each item you want to exclude. You may be able to use one for excluding one item, and use another for some other item. But don’t use both for the same.
Filter
FILTER
allows you to use sed
, grep
, or whatever other filters you would like to filter/replace chkrootkit’s output.
Opening up /etc/chkrootkit/chkrootkit.conf
, you’ll see the FILTER=
line. It’s a regular expression of what to ignore.
FILTER="sed -re 's![[:alnum:]]+: PACKET SNIFFER\(((/lib/systemd/systemd-networkd|(/usr)?/sbin/(dhclient|dhcpc?d[0-9]*|wpa_supplicant|NetworkManager))\[[0-9]+\](, )?)+\)!<interface>: PACKET SNIFFER\([systemd-networkd|dhclient|dhcpd|dhcpcd|wpa_supplicant|NetworkManager]{PID}\)!' -e 's/(! [[:alnum:]+-]+)\s+[0-9]+/\1 {PID}/'"
The above issue was caused because /usr/lib/systemd/systemd-networkd
was specified as /lib/systemd/systemd-networkd
in the filter.
...PACKET SNIFFER\(((/lib/systemd/systemd-networkd|(/usr)?/sbin/(dhclient|dhcpc?d[0-9]*...
^ no /usr was used, unlike how ^ here it is
Thus the answer is simple, add (/usr)?
...PACKET SNIFFER\((((/usr)?/lib/systemd/systemd-networkd|(/usr)?/sbin/(dhclient|dhcpc?d[0-9]*...
Thus giving you
FILTER="sed -re 's![[:alnum:]]+: PACKET SNIFFER\((((/usr)?/lib/systemd/systemd-networkd|(/usr)?/sbin/(dhclient|dhcpc?d[0-9]*|wpa_supplicant|NetworkManager))\[[0-9]+\](, )?)+\)!<interface>: PACKET SNIFFER\([systemd-networkd|dhclient|dhcpd|dhcpcd|wpa_supplicant|NetworkManager]{PID}\)!' -e 's/(! [[:alnum:]+-]+)\s+[0-9]+/\1 {PID}/'"
Then try it again.
/etc/cron.daily/chkrootkit
If the exclude was successful, it won’t show any output.
Ignore file
IGNORE_FILE
is not as powerful as the Filter option, but may be easier. It uses the file /etc/chkrootkit/chkrootkit.ignore
and can use egrep
regular expressions.
For the above issue, we’d use this line. Note how I had to replace (
with \(
, and [
with \[
. As well as their counterparts.
eth0: PACKET SNIFFER\(/usr/lib/systemd/systemd-networkd\[.*\]\)
Warning
Do not leave an empty line in the file, or it will exclude all lines from the output.
Save the file, and try it again.
/etc/cron.daily/chkrootkit
If the exclude was successful, it won’t show any output.
Docker
In docker there are interfaces that will change their name with each boot and even each time applications are added or removed. Thus they will show up in chkrootkit’s report.
From the output:
chkrootkit output was not as expected.
The difference is:
--- [ BEGIN: diff -u /var/log/chkrootkit/log.expected /var/log/chkrootkit/log.today ] ---
--- /var/log/chkrootkit/log.expected
+++ /var/log/chkrootkit/log.today
@@ -255,8 +255,8 @@
+br-238bc6070667: not promisc and no packet sniffer sockets
+br-a7b7812cce5f: not promisc and no packet sniffer sockets
-br-ab1b2e3f5ceb: not promisc and no packet sniffer sockets
-br-a7ed973cd3a0: not promisc and no packet sniffer sockets
We’ll use the Ignore
file to exclude these.
Open /etc/chkrootkit/chkrootkit.ignore
and add the following line.
^br-[0-9a-f]+: not promisc and no packet sniffer sockets$
Warning
Do not leave an empty line in the file, or it will exclude all lines from the output.
This looks for any like that starts with br
, has an interface name like a7b7812cce5f
and ends in the text not promisc and no packet sniffer sockets
.
Run the cronjob again
/etc/cron.daily/chkrootkit
And now it should only show that it’s removing the interfaces.
chkrootkit output was not as expected.
The difference is:
--- [ BEGIN: diff -u /var/log/chkrootkit/log.expected /var/log/chkrootkit/log.today ] ---
--- /var/log/chkrootkit/log.expected
+++ /var/log/chkrootkit/log.today
@@ -255,8 +255,8 @@
-br-238bc6070667: not promisc and no packet sniffer sockets
-br-a7b7812cce5f: not promisc and no packet sniffer sockets
To update the expected output, run (as root)
# cp -a -f /var/log/chkrootkit/log.today /var/log/chkrootkit/log.expected
If it looks good, then accept it and you’re good to go.
cp -a -f /var/log/chkrootkit/log.today /var/log/chkrootkit/log.expected
Using Filter to exclude br instead
We could have modified the FILTER=
by using a | grep ...
, but this adds more complexity to the filter
option. Still, if you have a complex situation, this may be helpful.
Info
No need to do this if you’ve already used the above ignore
file to exclude it. Consider this extra credit.
Open /etc/chkrootkit/chkrootkit.conf
and on the FILTER=
line add this to the end, before the last quote mark. This will remove any line that starts with “br-” and contains “not promisc and no packet sniffer sockets”.
| grep -Ev '^br-[0-9a-f]+: not promisc and no packet sniffer sockets$'
So it looks something like this (scroll all the way to the right,and make sure ‘copy’ isn’t blocking your view).
FILTER="sed -re 's![[:alnum:]]+: PACKET SNIFFER\((((/usr)?/lib/systemd/systemd-networkd|(/usr)?/sbin/(dhclient|dhcpc?d[0-9]*|wpa_supplicant|NetworkManager))\[[0-9]+\](, )?)+\)!<interface>: PACKET SNIFFER\([systemd-networkd|dhclient|dhcpd|dhcpcd|wpa_supplicant|NetworkManager]{PID}\)!' -e 's/(! [[:alnum:]+-]+)\s+[0-9]+/\1 {PID}/' | grep -Ev '^br-[0-9a-f]+: not promisc and no packet sniffer sockets$'"
Note
I could have added -e 's/^br-*//g'
to the filter line, however this would have just left an empty line for each br
network. So when an app was added or removed (and thus a docker br
sub-network was created/deleted), it would have added or removed an empty line. And thus sent out an unnecessary email.
Run the cronjob again
/etc/cron.daily/chkrootkit
And it will show
chkrootkit output was not as expected.
The difference is:
--- [ BEGIN: diff -u /var/log/chkrootkit/log.expected /var/log/chkrootkit/log.today ] ---
--- /var/log/chkrootkit/log.expected
+++ /var/log/chkrootkit/log.today
@@ -258,17 +258,17 @@
-br-238bc6070667: not promisc and no packet sniffer sockets
-br-a7b7812cce5f: not promisc and no packet sniffer sockets
--- [ END: diff -u /var/log/chkrootkit/log.expected /var/log/chkrootkit/log.today ] ---
To update the expected output, run (as root)
# cp -a -f /var/log/chkrootkit/log.today /var/log/chkrootkit/log.expected
And that’s what we want. We can save it.
cp -a -f /var/log/chkrootkit/log.today /var/log/chkrootkit/log.expected
Conclusion
And with that, we are a bit more secure, knowing we’ll be alerted to the presence of a rootkit on our system.
For more on rootkits, see how to setup rkhunter.