Major release: Lynis 3.x

After almost a year of work, we are excited to share news about the major 3.x release! It is major for multiple reasons, including the number of submissions from the community and some breaking changes. Some core functions have been rewritten and several new functions were added.

Another important area for this release is security. Being a security tool, we want Lynis to be as safe as possible, even though shell script is not specifically known for that. So this subject received additional focus on that as well.

Special thanks

Before talking about all new features and changes, let’s first thank a few individuals who contributed in a special way to this release. Their work shaped not only this release but also the future of Lynis.

Sander Bos discovered several security issues on how Lynis deals with the input and output of data. Based on his work, we requested several CVEs and patched the related areas. Furthermore, it inspired us to apply additional security measures to prevent similar issues. Thanks Sander, for your great insights, patience, and work!

Another person that deserves a big thanks is Topi Miettinen. His recent code contributions are of good quality, making it easy for the Lynis project to review and merge them. Most of his contributed work is now part of this major release. Thanks!

Breaking changes

So this new Lynis release might also break a few things. Let’s have a detailed look at them. This way you can determine what is applicable to your situation and resolve them.

Profiles

Especially when it comes to parsing your custom profile. If you are using the old-style notation, then the following message might show up:

[WARNING]: Your profile contains old-style configuration entries. See log file for more details and how to convert these entries

If you receive this message, then most likely you have to adjust your custom.prf. Look in the default profile (default.prf) to see the correct notation of a particular entry.

Background: In early versions, Lynis used a colon to split a key/value pair and underscores (e.g. is_enabled:1). In newer versions, we moved to a value assignment by using the equals (=) sign and dashes (e.g. is-enabled=1). Readability and simplicity was the rationale to make this change.

Command line options

Some of the options (like -c) are there from the very beginning. Since Lynis 2.x these vague options were rewritten to more instructive commands (-c became audit system). Vague command-line options have no place in easy-to-use software. With Lynis 3.x we decided to start removing them. To encourage users that still use the old switches, we will show when an option was deprecated and what switch or command has replaced it.

This option (-c) is deprecated.
Use: lynis audit system [options]

Tip: check your cron job. Are you still using an old command-line switch?

Security

Let’s talk about security! This major release comes with additional safeguards to make Lynis safer to use and harder to misuse. To better understand the new and enhanced security measures, it may be a good thing to look at the discovered issues first.

Vulnerabilities

With the help of some skilled individuals, we found some weaknesses in how Lynis parses data returned by common system tools. It made some assumptions that the output could be trusted. This approach is fine for most systems and tools, as data is correctly filtered or have no special characters in it. But if a system does host malicious users, things might change. One issue was discovered related to the log and report file. Another issue is information disclosure. Let’s have a look at the log file and report file first.

Vulnerability: dealing with log and report data

When Lynis performs its scan, it may write detailed information in its log file. This data is useful for learning what specifically was tested and discovered. Then there is useful data about the audit itself and stored in the report file (lynis-report.dat). Think data such as OS information, installed software packages, etc.

Most of the data stored in the log file and report file is simple text. If one is to manipulate that, then this still does not really introduce a vulnerability. The exception is when some of this data is parsed later and reused. That is exactly was happens near the end of the audit and in some specific tests. So if an attacker can manipulate the log file or report file, it may result in unexpected behavior along the way.

With the detailed help of Sander Bos, a weak spot was discovered when running Lynis as a non-privileged user. Even with some checks in place, it was possible to circumvent the safety checks. This makes it possible for systems that have no relevant security measure, to hijack the log and report files by setting up a symlink. Linux systems have since kernel 3.6 a way to guard against these symlink attacks. The relevant sysctl keys are fs.protected_hardlinks and fs.protected_symlinks. So the specific attack probably won’t work on most systems, but in the end it is still a vulnerability.

To resolve any issues with hijacking files and possibly malicious data, we decided to no longer store the log file and report /tmp. Instead, when a non-privileged user runs Lynis, it will go to the personal home directory. For the root user (or privileged), it will still go to /var/log.

Vulnerability: information disclosure

Another issue that was discovered by Sander Bos is related to leaking the license key. During the data upload to a central system, there is a short window of time in which the license key can be discovered from the process table. The impact of the information disclosure is limited, as it won’t provide any access to existing accounts or data. Knowing the license key could be abused to flood a system with incorrect or useless data, or exhaust the maximum number of uploads per day.

Note: Most Lynis users will not have the license key configured, as this is limited to those using Lynis Enterprise. If you are using Linux, you can also use the hidepid option on /proc to prevent this information disclosure.

Security measure: additional input/output filtering

To counter possible unexpected behavior when running Lynis and external commands, we added several security safe-guards. One of them is to filter unexpected data, whenever it comes from profiles, the report, or the output of commands.

Accept Known Good

Where possible, we limit the data to characters that we expect to be returned, the so-called Accept-Known-Good approach. For example, most of the values defined in the profile could be limited to a regular expression containing a fixed set (e.g. a-z, A-Z, 0-9, and a hyphen). When unexpected characters are discovered during the parsing of the profile, program execution will stop. Lynis will quit and notify the user.

Reject known bad

Sometimes we can’t be sure about the input or output. This is especially challenging with provided program parameters or output of external tools. The user could provide unexpected characters, tools may crash and return garbage. If we don’t know what to expect, we use the Reject-Known-Bad approach. For example, filtering out escape characters or limit output to just a single line. Another option is to have the od command convert the output, before we ingest it. Nothing is fool-proof, but every measure in this layered security approach may reduce the risk.

Function: SafeInput

Besides performing input and output validation, we want to keep the code as simple as possible. This is especially needed when there is a repeat similar actions, such as calling for an external tool and parse the output. To help with this, the function SafeInput uses the described approaches above.

Security measure: $PATH

Most users will have a common set of directories listed in their PATH variable, such as /bin, /sbin, /usr/bin, etc. Lynis uses this list to determine where to look for binaries. As this is also some form of input, additional checks have been added in this area as well. Because we want to trust every single user, but who knows what odd things people might have in there, by accident or on purpose…

New tests

This major release also extends the existing set of tests by at least 20, and includes are variety of areas. Although too much to name, it was especially the cryptography group that got several new tests, such as tests for disk encryption and the use of entropy enhancing generators.

Tip: you can easily write your own tests, as Lynis is written in shell script. Create the file tests_custom in the includedir (run: lynis show includedir). Use the tests_custom.template file to see some examples, or look into the existing tests on how they work.

Operating systems and end-of-life detection

Another area that received some attention is the OS detection routine itself. Especially with more Linux distributions that switched to systemd as its service manager (and what not…), some of the OS detection was simplified and more structured.

Improved OS support and functions

Lynis was originally developed on a FreeBSD system and supported a wide range of operating systems at its first release. We are proud that Lynis is still a lightweight tool and yet supports so many platforms. At the same time, some generic tests or functions might fail. This major release holds several patches to improve OS detection and execution tests and functions.

EOL detection

While we understand that not everyone can run the latest and greatest version of an operating system, there are still many companies using end-of-life systems. Although we can’t change that, we can at least flag them and inform the user. Maybe it helps to convince management that another system imposes extra risk and additional measures are needed.

Since Lynis 2.7.2 a function was added to do the end-of-life check. The operating system together with the end-of-life timestamp is compared against the current date and time. Did you go over the end-of-life? Then a message will be displayed. A manual check can be done by using lynis show eol. This major release improved the end-of-life check and several entries were added with the help of the community.

Migration tips from 2.x to 3.x

We suggest all users migrating as early as possible to the new 3.x release. The main reason is that there will be no new 2.x releases and all new changes will be part of the 3.x branch. Depending on your operating system and software repositories that are used, the switch may be as simple as doing a package upgrade. However, we do suggest you do perform some basic testing first.

Test the upgrade

If you installed Lynis as a package, you can fairly easily test if your configuration keeps working after upgrading. Here is one approach:

  • Step 1: deinstall your Lynis package (e.g. apt remove lynis), but leave the existing configuration files
  • Step 2: download Lynis from GitHub (using git clone or download the tarball)
  • Step 3: run lynis show profiles
  • Step 4: got an error on this command? See the tips in this post
  • Step 5: no error? Great, confirm that your custom.prf (e.g. /etc/lynis/custom.prf) shows up in the output
  • Step 6: run lynis system audit
  • Step 7: check for any issues (old configuration entries, unexpected characters, unexpected screen output)
  • Step 8: remove the new 3.x version and clean up the directory
  • Step 9: install the 2.x version again (apt install lynis)
  • Step 10: check your cronjob and replace old command flags in advance (e.g. replace -c to audit system)

By performing these steps should be able to determine if something breaks when switching all your systems to the new 3.x release. Most likely the impact will be limited, but better safe than sorry.

Don’t copy the default profile!

Did you make a copy of the default profile? This is the time to start fresh. As shown in the default profile, only copy the relevant entries that you want to change into your custom.prf. The default profile is always loaded and sets the default values. The custom profile builds upon these defaults and defines your specific preferences. So keep that custom profile small and readable!

What is next?

The first release of Lynis was in 2007. Even though it is already 13 years ago Lynis is still relevant, with new users every day. Therefore this major release is the beginning of a new era of the tool. Let’s have a look at the future.

More frequent releases again!

Now that we finished this major release, the time between two releases will be much shorter again. You can expect one or two releases per month like we used to do. The project remains healthy and having regular releases shows both users and contributors that changes are implemented.

The focus will be on completing several aspects on the side-line of the project, such as the website. One area that we like to improve is documentation. Not everyone is a native English speaker, so we like to refresh all documentation pages and make them available in more different languages.

To get the documentation translated, we will ask our community to chime in, as we did in the past for translation several parts of Lynis itself. Speaking about that, some of the output is still English-only. So that is something else we like to cover.

Want to help?

The beauty of open-source software is that it allows many people to use the software. During the last years, we have seen a great increase in contributions, from translations to code enhancements. At the same time it is completely understandable that depending on your time and skill set, your options to help are limited. Events like the COVID-19 pandemic will put even more pressure on all of us. Still, there are few smalls things you can do that may result in a great impact. Here are some ideas:

  • Send out a tweet about your favorite tool(s) and what you like about it
  • Have a look at the available translations and see if you can help there
  • Read the documentation carefully, point out areas that can be improved, such as grammar issues
  • Reach out to your favorite projects and send a small “Thank you”
  • Share this blog post with friends or colleagues

Enjoy the new release

I hope you will like the new Lynis release. Give it a try, and let me know how you like it. Stay safe!

Feedback

Small picture of Michael Boelen

This article has been written by our Linux security expert Michael Boelen. With focus on creating high-quality articles and relevant examples, he wants to improve the field of Linux security. No more web full of copy-pasted blog posts.

Discovered outdated information or have a question? Share your thoughts. Thanks for your contribution!

Mastodon icon