Merge branch 'master' into patch_3

This commit is contained in:
Michael Boelen 2019-07-14 08:36:47 +02:00 committed by GitHub
commit 0bdcb57763
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 1958 additions and 582 deletions

View File

@ -1,5 +1,115 @@
# Lynis Changelog
## Lynis 3.0.0 (not released yet)
This is a major release of Lynis and includes several big changes.
Some of these changes may break your current usage of the tool, so test before
deployment!
### Breaking changes
- Some commands or switches are deprecated or removed
- Format of all profile options converted (from key:value to key=value)
- Non-interactive by default (use --wait option to pause between groups of tests)
### Security
An important focus area for this release is on security. We added several
measures to further tighten any possible misuse.
### Added
- Security: test PATH and warn or exit on discovery of dangerous location
- Security: additional safeguard by testing if common system tools are available
- Security: test parameters and arguments for presence of control characters
- Security: filtering out unexpected characters from profiles
- Security: test if setuid bit is set on Lynis binary
- New function: DisplayWarning - show a warning on the screen
- New function: Equals - compare two strings
- New function: Readonly - mark variable read-only (security)
- New function: SafeFile - test file type and call permission check
- New function: SafeInput - check for safe input (security)
- New profile option: disable-plugin - disables a single plugin
- New profile option: ssl-certificate-paths-to-ignore - ignore a path
- New test: CRYP-7930 - disk or file system encryption testing
- New test: PROC-3802 - Check presence of prelink tooling
- New report key: openssh_daemon_running
- New command: lynis generate systemd-units
- Measure timing of tests and report slow tests (10+ seconds)
### Changed
- Function: CheckItem - returns only exit code (ITEM_FOUND value is dropped)
- Profiles: unused options removed
- Profiles: message is displayed when old format "key:value" is used
- Security: the 'nounset' (set -u) parameter is now activated by default
- Use only locations from PATH environment variable, unless it is not defined
- Show 'lynis generate hostids' when they are missing
- NAME-4408 - corrected Report function call
- NETW-3032 - small rewrite of test and extended with addrwatch
- PROC-3602 - allow different root directory
- PROC-3612 - show 'Not found' instead of 'OK'
- PROC-3614 - show 'Not found' instead of 'OK'
- SSH-7402 - detect other SSH daemons like dropbear
- Whow changelog works again for newer versions
- systemd service file adjusted
- bash completion script extended
---------------------------------------------------------------------------------
## Lynis 2.7.5 (2019-06-24)
### Added
- Danish translation
- Slackware end-of-life information
- Detect BSD-style (rc.d) init in Linux systems
- Detection of Bro and Suricata (IDS)
### Changed
- Corrected end-of-life entries for CentOS 5 and 6
- AUTH-9204 - change name to check in /etc/passwd file for QNAP devices
- AUTH-9268 - AIX enhancement to use correct find statement
- FILE-6310 - Filter on correct field for AIX
- NETW-3012 - set ss command as preferred option for Linux and changed output format
- List of PHP ini file locations has been extended
- Removed several pieces of the code as part of cleanup and code health
- Extended help
---------------------------------------------------------------------------------
## Lynis 2.7.4 (2019-04-21)
This is a bigger release than usual, including several new tests created by
Capashenn (GitHub). It is a coincidence that it is released exactly one month
after the previous version and on Easter. No easter eggs, only improvements!
### Added
- FILE-6324 - Discover XFS mount points
- INSE-8000 - Installed inetd package
- INSE-8100 - Installed xinetd package
- INSE-8102 - Status of xinet daemon
- INSE-8104 - xinetd configuration file
- INSE-8106 - xinetd configuration for inactive daemon
- INSE-8200 - Usage of TCP wrappers
- INSE-8300 - Presence of rsh client
- INSE-8302 - Presence of rsh server
- Detect equery binary detection
- New 'generate' command
### Changed
- AUTH-9278 - Test LDAP in all PAM components on Red Hat and other systems
- PKGS-7410 - Add support for DPKG-based systems to gather installed kernel packages
- PKGS-7420 - Detect toolkit to automatically download and apply upgrades
- PKGS-7328 - Added global Zypper option --non-interactive
- PKGS-7330 - Added global Zypper option --non-interactive
- PKGS-7386 - Only show warning when vulnerable packages were discovered
- PKGS-7392 - Skip test for Zypper-based systems
- Minor changes to improve text output, test descriptions, and logging
- Changed CentOS identifiers in end-of-life database
- AIX enhancement for IsRunning function
- Extended PackageIsInstalled function
- Improve text output on AIX systems
- Corrected lsvg binary detection
---------------------------------------------------------------------------------
## Lynis 2.7.3 (2019-03-21)
### Added

27
SECURITY.md Normal file
View File

@ -0,0 +1,27 @@
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 3.x.x | :white_check_mark: |
| 2.x.x | :white_check_mark: |
| < 2.x | :x: |
## Reporting a Vulnerability
To report a vulnerability, use security@cisofy.com
See our [security page](https://cisofy.com/security/) for more details.
## Preferred language
English
## Acknowledgments
https://cisofy.com/security/#thanks
## Other
See the latest 'security.txt' at https://cisofy.com/.well-known/security.txt

41
db/languages/da Normal file
View File

@ -0,0 +1,41 @@
ERROR_NO_LICENSE="Ingen licensnøgle konfigureret"
ERROR_NO_UPLOAD_SERVER="Ingen upload server konfigureret"
GEN_CHECKING="Tjekker"
GEN_CURRENT_VERSION="Nuværende version"
GEN_DEBUG_MODE="Fejlfindingstilstand"
GEN_INITIALIZE_PROGRAM="Initialiserer program"
GEN_LATEST_VERSION="Seneste version"
GEN_PHASE="Fase"
GEN_PLUGINS_ENABLED="Plugins aktiverede"
GEN_UPDATE_AVAILABLE="opdatering tilgængelig"
GEN_VERBOSE_MODE="Detaljeret tilstand"
GEN_WHAT_TO_DO="At gøre"
NOTE_EXCEPTIONS_FOUND="Undtagelser fundet"
NOTE_EXCEPTIONS_FOUND_DETAILED="Nogle usædvanlige hændelser eller information var fundet"
NOTE_PLUGINS_TAKE_TIME="Bemærk: plugins har mere omfattende tests og kan tage flere minutter at fuldføre"
NOTE_SKIPPED_TESTS_NON_PRIVILEGED="Sprang over tests på grund af ikke-privilegeret tilstand"
SECTION_CUSTOM_TESTS="Brugerdefinerede Tests"
SECTION_MALWARE="Malware"
SECTION_MEMORY_AND_PROCESSES="Hukommelse og Processer"
STATUS_DISABLED="DEAKTIVERET"
STATUS_DONE="FÆRDIG"
STATUS_ENABLED="AKTIVERET"
STATUS_NOT_ENABLED="IKKE AKTIVERET"
STATUS_ERROR="FEJL"
STATUS_FOUND="FUNDET"
STATUS_YES="JA"
STATUS_NO="NEJ"
STATUS_OFF="FRA"
STATUS_OK="OK"
STATUS_ON="TIL"
STATUS_NONE="INGEN"
STATUS_NOT_FOUND="IKKE FUNDET"
STATUS_NOT_RUNNING="KØRER IKKE"
STATUS_RUNNING="KØRER"
STATUS_SKIPPED="SPRUNGET OVER"
STATUS_SUGGESTION="FORSLAG"
STATUS_UNKNOWN="UKENDT"
STATUS_WARNING="ADVARSEL"
STATUS_WEAK="SVAG"
TEXT_YOU_CAN_HELP_LOGFILE="Du kan hjælpe ved at bidrage med din logfil"
TEXT_UPDATE_AVAILABLE="opdatering tilgængelig"

View File

@ -11,9 +11,9 @@
#
# CentOS
#
os:CentOS 5:2017-03-31:1490911200:
os:CentOS 6:2020-11-30:1606690800:
os:CentOS 7:2024-06-30:1719698400:
os:CentOS release 5:2017-03-31:1490911200:
os:CentOS release 6:2020-11-30:1606690800:
os:CentOS Linux release 7:2024-06-30:1719698400:
#
# FreeBSD - https://www.freebsd.org/security/unsupported.html
#
@ -42,5 +42,21 @@ os:Ubuntu 16.10:2017-07-01:1498860000:
os:Ubuntu 17.04:2018-01-01:1514761200:
os:Ubuntu 17.10:2018-07-01:1530396000:
os:Ubuntu 18.04:2023-05-01:1682892000:
os:Ubuntu 18.10:2019-07-01:1561932000:
os:Ubuntu 19.04:2020-01-01:1577833200:
os:Ubuntu 18.10:2019-07-18:1563400800:
os:Ubuntu 19.04:2020-01-01:1577833200:
#
# Slackware - https://en.wikipedia.org/wiki/Slackware#Releases
#
os:Slackware Linux 8.1:2012-08-01:1343768400:
os:Slackware Linux 9.0:2012-08-01:1343768400:
os:Slackware Linux 9.1:2012-08-01:1343768400:
os:Slackware Linux 10.0:2012-08-01:1343768400:
os:Slackware Linux 10.1:2012-08-01:1343768400:
os:Slackware Linux 10.2:2012-08-01:1343768400:
os:Slackware Linux 11.0:2012-08-01:1343768400:
os:Slackware Linux 12.0:2012-08-01:1343768400:
os:Slackware Linux 12.1:2013-12-09:1386540000:
os:Slackware Linux 12.2:2013-12-09:1386540000:
os:Slackware Linux 13.0:2018-07-05:1530738000:
os:Slackware Linux 13.1:2018-07-05:1530738000:
os:Slackware Linux 13.37:2018-07-05:1530738000:

View File

@ -84,6 +84,7 @@ CONT-8107:test:performance:containers::Check number of unused Docker containers:
CONT-8108:test:security:containers::Check file permissions for Docker files:
CORE-1000:test:performance:system_integrity::Check all system binaries:
CRYP-7902:test:security:crypto::Check expire date of SSL certificates:
CRYP-7930:test:security:crypto::Determine if system uses disk or file encryption:
DNS-1600:test:security:dns::Validating that the DNSSEC signatures are checked:
DBS-1804:test:security:databases::Checking active MySQL process:
DBS-1816:test:security:databases::Checking MySQL root password:
@ -169,11 +170,17 @@ HTTP-6712:test:security:webservers::Check nginx access logging:
HTTP-6714:test:security:webservers::Check for missing error logs in nginx:
HTTP-6716:test:security:webservers::Check for debug mode on error log in nginx:
HTTP-6720:test:security:webservers::Check Nginx log files:
INSE-8002:test:security:insecure_services::Check for enabled inet daemon:
INSE-8004:test:security:insecure_services::Check for enabled inet daemon:
INSE-8006:test:security:insecure_services::Check configuration of inetd when disabled:
INSE-8000:test:security:insecure_services::Installed inetd package:
INSE-8002:test:security:insecure_services::Status of inet daemon:
INSE-8004:test:security:insecure_services::Presence of inetd configuration file:
INSE-8006:test:security:insecure_services::Check configuration of inetd when it is disabled:
INSE-8016:test:security:insecure_services::Check for telnet via inetd:
INSE-8050:test:security:insecure_services:MacOS:Check for insecure services on macOS systems:
INSE-8100:test:security:insecure_services::Installed xinetd package:
INSE-8116:test:security:insecure_services::Insecure services enabled via xinetd:
INSE-8200:test:security:insecure_services::Usage of TCP wrappers:
INSE-8300:test:security:insecure_services::Presence of rsh client:
INSE-8302:test:security:insecure_services::Presence of rsh server:
KRNL-5622:test:security:kernel:Linux:Determine Linux default run level:
KRNL-5677:test:security:kernel:Linux:Check CPU options and support:
KRNL-5695:test:security:kernel:Linux:Determine Linux kernel version and release number:
@ -319,6 +326,7 @@ PKGS-7393:test:security:ports_packages::Check for Gentoo vulnerable packages:
PKGS-7394:test:security:ports_packages:Linux:Check for Ubuntu updates:
PKGS-7398:test:security:ports_packages::Check for package audit tool:
PKGS-7410:test:security:ports_packages::Count installed kernel packages:
PKGS-7420:test:security:ports_packages::Detect toolkit to automatically download and apply upgrades:
PRNT-2302:test:security:printers_spools:FreeBSD:Check for printcap consistency:
PRNT-2304:test:security:printers_spools::Check cupsd status:
PRNT-2306:test:security:printers_spools::Check CUPSd configuration file:
@ -332,6 +340,7 @@ PROC-3602:test:security:memory_processes:Linux:Checking /proc/meminfo for memory
PROC-3604:test:security:memory_processes:Solaris:Query prtconf for memory details:
PROC-3612:test:security:memory_processes::Check dead or zombie processes:
PROC-3614:test:security:memory_processes::Check heavy IO waiting based processes:
PROC-3802:test:security:memory_processes::Check presence of prelink tooling:
RBAC-6272:test:security:mac_frameworks::Check grsecurity presence:
SCHD-7702:test:security:scheduling::Check status of cron daemon:
SCHD-7704:test:security:scheduling::Check crontab/cronjobs:

View File

@ -1,30 +1,33 @@
#################################################################################
#
#
# Lynis - Scan Profile (default)
#
# This is the default profile and contains default values.
# Lynis - Default scan profile
#
#
#################################################################################
#
#
# SUGGESTION
# This profile provides Lynis with most of its initial values to perform a
# system audit.
#
#
# WARNINGS
# ----------
#
# Do NOT make changes to this file, instead copy your preferred settings to
# custom.prf and put it in the same directory as default.prf
# Do NOT make changes to this file. Instead, copy only your changes into
# the file custom.prf and put it in the same directory as default.prf
#
# To discover where your profiles are located: lynis show profiles
#
#
# Lynis performs a strict check on profiles to avoid the inclusion of
# possibly harmful injections. See include/profiles for details.
#
#
#################################################################################
#
# All empty lines or with the # prefix will be skipped
#
# More information about this plugin can be found in the documentation:
# https://cisofy.com/documentation/lynis/
#
#################################################################################
# Use colored output
@ -33,6 +36,9 @@ colors=yes
# Compressed uploads (set to zero when errors with uploading occur)
compressed-uploads=yes
# Amount of connections in WAIT state before reporting it as a suggestion
#connections-max-wait-state=5000
# Debug mode (for debugging purposes, extra data logged to screen)
#debug=yes
@ -42,20 +48,27 @@ error-on-warnings=no
# Use Lynis in your own language (by default auto-detected)
language=
# Lynis Enterprise license key
license-key=
# Log tests from another guest operating system (default: yes)
#log-tests-incorrect-os=yes
# Define if available NTP daemon is configured as a server or client on the network
# values: server or client (default: client)
#ntpd-role=client
# Defines the role of the system (personal, workstation or server)
machine-role=server
# Ignore some stratum 16 hosts (for example when running as time source itself)
#ntp-ignore-stratum-16-peer=127.0.0.1
# Profile name, will be used as title/description
profile-name=Default Audit Template
# Number of seconds to pause between every test (0 is no pause)
pause-between-tests=0
# Enable quick mode (no waiting for keypresses, same as --quick option)
quick=no
# Quick mode (do not wait for keypresses)
quick=yes
# Refresh software repositories to help detecting vulnerable packages
refresh-repositories=yes
@ -76,39 +89,20 @@ skip-plugins=no
#skip-test=SSH-7408:loglevel
#skip-test=SSH-7408:permitrootlogin
# Skip Lynis upgrade availability test (default: no)
#skip-upgrade-test=yes
# Locations where to search for SSL certificates (separate paths with a colon)
ssl-certificate-paths=/etc/apache2:/etc/dovecot:/etc/httpd:/etc/letsencrypt:/etc/pki:/etc/postfix:/etc/ssl:/opt/psa/var/certificates:/usr/local/psa/var/certificates:/usr/local/share/ca-certificates:/var/www:/srv/www
ssl-certificate-paths-to-ignore=/etc/letsencrypt/archive:
# Scan type - how deep the audit should be (light, normal or full)
test-scan-mode=full
# Upload data to central server
upload=no
# The hostname/IP address to receive the data
upload-server=
# Provide options to cURL (or other upload tool) when uploading data.
# upload-options=--insecure --> use HTTPS, but skip certificate check (e.g. self-signed)
upload-options=
# Verbose output
verbose=no
#################################################################################
#
# Upgrade and updating
# --------------------
#
# The old settings to do automatic updating are deprecated. It is suggested to
# use a package or deploy your the tarball via a custom script.
#
# The latest packages can be found at: https://packages.cisofy.com
#
#################################################################################
# Skip Lynis upgrade availability test (default: no)
#skip-upgrade-test=yes
#################################################################################
#
# Plugins
@ -119,10 +113,11 @@ verbose=no
# - Nothing happens if plugin isn't available
# - There is no order in execution of plugins
# - See documentation about how to use plugins and phases
# - Some are for Lynis Enterprise users only
#
#################################################################################
# Lynis Plugins (some are for Lynis Enterprise users only)
# Lynis plugins to enable
plugin=authentication
plugin=compliance
plugin=configuration
@ -149,17 +144,22 @@ plugin=system-integrity
plugin=systemd
plugin=users
# Disable a particular plugin (will overrule an enabled plugin)
#disable-plugin=authentication
#################################################################################
#
# Kernel options
# ---------------
# sysctl:<sysctl Key>:<Expected Value>:<Hardening Points>:<Description>:
# configdate=, followed by:
#
# Sysctl key = name
# Expected value = value of sysctl key
# Hardening points = Number of hardening points. For most keys 1 HP will be suitable
# Description = Text description of key
# - Type = Set to 'sysctl'
# - Setting = value of sysctl key (e.g. kernel.sysrq)
# - Expected value = Preferred value for key (e.g. 0)
# - Hardening Points = Number of hardening points (typically 1 point per key) (1)
# - Description = Textual description about the sysctl key(Disable magic SysRQ)
# - Related file or command = For example, sysctl -a to retrieve more details
# - Solution field = Specifies more details or where to find them (url:URL, text:TEXT, or -)
#
#################################################################################
@ -269,86 +269,58 @@ config-data=sysctl;security.bsd.hardlink_check_gid;1;1;Unprivileged processes ar
config-data=sysctl;security.bsd.hardlink_check_uid;1;1;Unprivileged processes are not allowed to create hard links to files which are owned by other users;-;category:security;
#################################################################################
#
# Apache options
# columns: (1)apache : (2)option : (3)value
#
#################################################################################
apache:ServerTokens:Prod:
#################################################################################
#
# OpenLDAP options
# columns: (1)openldap : (2)file : (3)option : (4)expected value(s)
#
#################################################################################
openldap:slapd.conf:permissions:640-600:
openldap:slapd.conf:owner:ldap-root:
#################################################################################
#
# NTP options
#
#################################################################################
# Ignore some stratum 16 hosts (for example when running as time source itself)
#ntp-ignore-stratum-16-peer=127.0.0.1
#################################################################################
#
# File/directories permissions (currently not used yet)
#
#################################################################################
# Scan for exact file name match
#[scanfiles]
#scanfile:/etc/rc.conf:FreeBSD configuration:
# Scan for exact directory name match
#[scandirs]
#scandir:/etc:/etc directory:
#################################################################################
#
# permfile
# ---------------
# permfile:file name:file permissions:owner:group:action:
# permfile=file name:file permissions:owner:group:action:
# Action = NOTICE or WARN
# Examples:
# permfile:/etc/test1.dat:600:root:wheel:NOTICE:
# permfile:/etc/test1.dat:640:root:-:WARN:
# permfile=/etc/test1.dat:600:root:wheel:NOTICE:
# permfile=/etc/test1.dat:640:root:-:WARN:
#
#################################################################################
#permfile:/etc/inetd.conf:rw-------:root:-:WARN:
#permfile:/etc/fstab:rw-r--r--:root:-:WARN:
permfile:/etc/lilo.conf:rw-------:root:-:WARN:
#permfile=/etc/inetd.conf:rw-------:root:-:WARN:
#permfile=/etc/fstab:rw-r--r--:root:-:WARN:
permfile=/boot/grub2/grub.cfg:rw-------:root:root:WARN:
permfile=/boot/grub/grub.cfg:rw-------:root:root:WARN:
permfile=/boot/grub2/user.cfg:rw-------:root:root:WARN:
permfile=/etc/at.allow:rw-------:root:-:WARN:
permfile=/etc/at.deny:rw-------:root:-:WARN:
permfile=/etc/cron.allow:rw-------:root:-:WARN:
permfile=/etc/cron.deny:rw-------:root:-:WARN:
permfile=/etc/crontab:rw-------:root:-:WARN:
permfile=/etc/group:rw-r--r--:root:-:WARN:
permfile=/etc/group-:rw-r--r--:root:-:WARN:
permfile=/etc/gshadow:---------:root:-:WARN:
permfile=/etc/gshadow-:---------:root:-:WARN:
permfile=/etc/hosts.allow:rw-r--r--:root:root:WARN:
permfile=/etc/hosts.deny:rw-r--r--:root:root:WARN:
permfile=/etc/issue:rw-r--r--:root:root:WARN:
permfile=/etc/issue.net:rw-r--r--:root:root:WARN:
permfile=/etc/lilo.conf:rw-------:root:-:WARN:
permfile=/etc/motd:rw-r--r--:root:root:WARN:
permfile=/etc/passwd:rw-r--r--:root:-:WARN:
permfile=/etc/passwd-:rw-r--r--:root:-:WARN:
permfile=/etc/shadow:---------:root:-:WARN:
permfile=/etc/shadow-:---------:root:-:WARN:
permfile=/etc/ssh/sshd_config:rw-------:root:-:WARN:
#################################################################################
#
# permdir
# ---------------
# permdir:directory name:file permissions:owner:group:action when permissions are different:
# permdir=directory name:file permissions:owner:group:action when permissions are different:
#
#################################################################################
permdir:/root/.ssh:rwx------:root:-:WARN:
# Scan for a program/binary in BINPATHs
#scanbinary:Rootkit Hunter:rkhunter:
# Amount of connections in WAIT state before reporting it as a suggestion
#connections-max-wait-state=5000
permdir=/root/.ssh:rwx------:root:-:WARN:
permdir=/etc/cron.d:rwx------:root:root:WARN:
permdir=/etc/cron.daily:rwx------:root:root:WARN:
permdir=/etc/cron.hourly:rwx------:root:root:WARN:
permdir=/etc/cron.weekly:rwx------:root:root:WARN:
permdir=/etc/cron.monthly:rwx------:root:root:WARN:
# Ignore some specific home directories
@ -356,12 +328,6 @@ permdir:/root/.ssh:rwx------:root:-:WARN:
# checks, like file permissions, SSH and other configuration files
#ignore-home-dir=/home/user
# Do not log tests with another guest operating system (default: yes)
#log-tests-incorrect-os=no
# Define if available NTP daemon is configured as a server or client on the network
# values: server or client (default: client)
#ntpd-role=client
# Allow promiscuous interfaces
# <option>:<promiscuous interface name>:<description>:
@ -395,21 +361,10 @@ permdir:/root/.ssh:rwx------:root:-:WARN:
#################################################################################
#
# SSL certificates
#
#################################################################################
# Locations where to search for SSL certificates
ssl-certificate-paths=/etc/apache2:/etc/dovecot:/etc/httpd:/etc/letsencrypt:/etc/pki:/etc/postfix:/etc/ssl:/opt/psa/var/certificates:/usr/local/psa/var/certificates:/usr/local/share/ca-certificates:/var/www:/srv/www
#################################################################################
#
# Lynis Enterprise options
# -----------------
# ------------------------
#
#################################################################################
@ -423,6 +378,9 @@ ssl-certificate-paths=/etc/apache2:/etc/dovecot:/etc/httpd:/etc/letsencrypt:/etc
#hostid=40-char-hash
#hostid2=64-char-hash
# Lynis Enterprise license key
license-key=
# Proxy settings
# Protocol (http, https, socks5)
#proxy-protocol=https
@ -443,9 +401,18 @@ compliance-standards=cis,hipaa,iso27001,pci-dss
# Provide the name of the customer/client
#system-customer-name=mycustomer
# Upload data to central server
upload=no
# The hostname/IP address to receive the data
upload-server=
# Provide options to cURL (or other upload tool) when uploading data.
# upload-options=--insecure (use HTTPS, but skip certificate check for self-signed certificates)
upload-options=
# Link one or more tags to a system
#tags=db,production,ssn-1304
#EOF

View File

@ -3,6 +3,5 @@
debug=yes
developer-mode=yes
quick=yes
strict=yes
verbose=yes

View File

@ -1,6 +1,6 @@
# bash completion for lynis
# version 1.0.0 (22 September 2014)
# version 1.0.1 (2019-07-13)
# Michael Boelen <michael.boelen@cisofy.com>
# lynis(8) completion
@ -10,7 +10,7 @@ _lynis()
# opts nodig nosig
COMPREPLY=()
_get_comp_words_by_ref cur prev
_get_comp_words_by_ref cur prev words
if [ $COMP_CWORD -eq 1 ]; then
# first parameter on line
@ -19,24 +19,134 @@ _lynis()
COMPREPLY=( $( compgen -W '--help --info --version' -- "$cur" ) )
;;
*)
COMPREPLY=( $( compgen -W 'audit --help --info --version' -- "$cur" ) )
COMPREPLY=( $( compgen -W 'audit generate show' -- "$cur" ) )
;;
esac
return 0
return 0
elif [ $COMP_CWORD -eq 4 ]; then
# Stop after some specifics
if [ "${COMP_WORDS[1]}" = "show" -a "${COMP_WORDS[2]}" = "details" ]; then
return 0
fi
fi
# Check previous argument to share the available options
case $prev in
audit)
COMPREPLY=( $( compgen -W 'dockerfile system ' -- "$cur" ) )
;;
show)
COMPREPLY=( $( compgen -W 'help version ' -- "$cur" ) )
COMPREPLY=( $( compgen -W 'categories changelog commands dbdir details environment eol groups help hostids includedir language license logfile man options os pidfile plugindir profiles release releasedate report settings tests version workdir ' -- "$cur" ) )
;;
# Related items to show (lynis show XYZ)
categories)
return 0
;;
changelog)
return 0
;;
commands)
return 0
;;
dbdir)
return 0
;;
details)
local dbfile=""
local dirs="/data/development/lynis /usr/local/lynis /usr/share/lynis"
for d in ${dirs}; do
if [ -f "${d}/db/tests.db" ]; then
local dbfile="/data/development/lynis/db/tests.db"
fi
done
if [ -f "${dbfile}" ]; then
local suggestions=($(compgen -W "$(awk -F: '$1 ~ /^[A-Z]/ {print $1}' ${dbfile})" -- "${cur}"))
COMPREPLY=("${suggestions[@]}")
else
COMPREPLY=($(compgen -W "TEST-1234" -- "$cur"))
fi
;;
environment)
return 0
;;
eol)
return 0
;;
groups)
return 0
;;
help)
return 0
;;
hostids)
if [ "${COMP_WORDS[1]}" = "generate" -a "${COMP_WORDS[2]}" = "hostids" ]; then
COMPREPLY=($(compgen -W "save" -- "$cur"))
else
return 0
fi
;;
includedir)
return 0
;;
language)
return 0
;;
license)
return 0
;;
logfile)
return 0
;;
man)
return 0
;;
options)
return 0
;;
os)
return 0
;;
pidfile)
return 0
;;
plugindir)
return 0
;;
profiles)
return 0
;;
release)
return 0
;;
releasedate)
return 0
;;
report)
return 0
;;
settiings)
return 0
;;
tests)
return 0
;;
version)
return 0
;;
workdir)
return 0
;;
generate)
COMPREPLY=( $( compgen -W 'hostids ' -- "$cur" ) )
;;
# Options
--auditor)
COMPREPLY=( '"Mr. Auditor"' )
return 0
#return 0
;;
--check-update|--help|--info|--version)
# all other options are noop with this command

View File

@ -5,19 +5,26 @@
#################################################################################
#
# - Adjust path to link to location where Lynis binary is installed
# - Place this file together with the timer file in systemd directory
# - Run: systemctl enable lynis.service
#
# - Place this file together with the lynis.timer file in the related
# systemd directory (e.g. /etc/systemd/system/)
#
# - See details in lynis.timer file
#
#################################################################################
[Unit]
Description=Lynis security audit and vulnerability scan
Description=Security audit and vulnerability scanner
Documentation=https://cisofy.com/docs/
[Service]
Nice=19
IOSchedulingClass=best-effort
IOSchedulingPriority=7
Type=simple
ExecStart=/path/to/lynis -c --cronjob
ExecStart=/path/to/lynis audit system --cronjob
[Install]
WantedBy=multi-user.target
#EOF

View File

@ -4,17 +4,23 @@
#
#################################################################################
#
# - Place this file together with the service file in systemd directory
# - Run: systemctl enable lynis.timer
# systemctl start lynis.service
# - Place this file together with the lynis.service file in the related
# systemd directory (e.g. /etc/systemd/system)
#
# - Tell systemd you made changes
# systemctl daemon-reload
#
# - Enable and start the timer (so no reboot is needed):
# systemctl enable --now lynis.timer
#
#################################################################################
[Unit]
Description=Daily run for Lynis security audit and vulnerability scan
Description=Daily timer for the Lynis security audit and vulnerability scanner
[Timer]
OnCalendar=daily
RandomizedDelaySec=1800
Persistent=false
[Install]

View File

@ -42,18 +42,39 @@
Display --indent 2 --text "- Checking system binaries..."
LogText "Status: Starting binary scan..."
# Test if our PATH variable provides a set of paths
# If so, reverse the order. If we discover the same binary multiple times, the one first in PATH
# should be used.
# If PATH is empty, we use the predefined list in include/consts. Common paths first, then followed
# by more specific paths. This helps on the slightly ancient UNIX derivatives.
# Notes:
# - If PATH is empty, we use the predefined list in include/consts
# - Common paths first, then followed by more specific paths. This helps on the slightly ancient UNIX derivatives.
# - Avoid sorting the path list, as this might result in incorrect order of finding binaries (e.g. awk binary)
# Test if our PATH variable provides a set of paths. If so, reverse the order. If we discover the same binary
# multiple times, the one first in PATH should be used.
if [ ! -z "${PATH}" ]; then
PATH_REVERSED=$(echo ${PATH} | awk -F: '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }')
BIN_PATHS=$(echo "${PATH_REVERSED} ${BIN_PATHS}" | tr ':' ' ')
BIN_PATHS=$(echo "${PATH_REVERSED}" | tr ':' ' ')
fi
# Avoid sorting, as this might result in incorrect order of finding binaries (e.g. awk binary)
#SORTED_BIN_PATHS=$(echo ${BIN_PATHS} | tr ' ' '\n' | sort | uniq | tr '\n' ' ')
# First test available locations that may be suspicious or dangerous
for SCANDIR in ${BIN_PATHS}; do
FOUND=0
if [ "${SCANDIR}" = "." ]; then FOUND=1; MSG="Found single dot (.) in PATH"
elif [ "${SCANDIR}" = ".." ]; then FOUND=1; MSG="Found double dot (..) in PATH"
elif echo ${SCANDIR} | grep '^\.\.' > /dev/null; then FOUND=1; MSG="Found path starting with double dot (..) in PATH"
elif echo ${SCANDIR} | grep '^[a-zA-Z]' > /dev/null; then FOUND=1; MSG="Found relative path in PATH"
fi
if [ ${FOUND} -eq 1 ]; then
# Stop execution if privileged, otherwise continue but warn user
if [ ${PRIVILEGED} -eq 1 ]; then
ExitFatal "Possible riskful location (${SCANDIR}) in PATH discovered. Quitting..."
else
Display --indent 4 --text "Warning: suspicious location (${SCANDIR}) in PATH"
ReportWarning "${TEST_NO}" "Possible riskful location in PATH discovered" "text:${MSG}"
sleep 1
fi
fi
done
# Now perform binary detection
for SCANDIR in ${BIN_PATHS}; do
LogText "Test: Checking binaries in directory ${SCANDIR}"
ORGPATH=""
@ -99,6 +120,7 @@
afick.pl) AFICKBINARY=${BINARY}; LogText " Found known binary: afick (file integrity checker) - ${BINARY}" ;;
aide) AIDEBINARY=${BINARY}; LogText " Found known binary: aide (file integrity checker) - ${BINARY}" ;;
apache2) HTTPDBINARY=${BINARY}; LogText " Found known binary: apache2 (web server) - ${BINARY}" ;;
apt) APTBINARY=${BINARY}; LogText " Found known binary: apt (package manager) - ${BINARY}" ;;
arch-audit) ARCH_AUDIT_BINARY="${BINARY}"; LogText " Found known binary: arch-audit (auditing utility to test for vulnerable packages) - ${BINARY}" ;;
auditd) AUDITDBINARY=${BINARY}; LogText " Found known binary: auditd (audit framework) - ${BINARY}" ;;
awk) AWKBINARY=${BINARY}; LogText " Found known binary: awk (string tool) - ${BINARY}" ;;
@ -109,6 +131,7 @@
base64) BASE64BINARY="${BINARY}"; LogText " Found known binary: base64 (encoding tool) - ${BINARY}" ;;
blkid) BLKIDBINARY="${BINARY}"; LogText " Found known binary: blkid (information about block devices) - ${BINARY}" ;;
bootctl) BOOTCTLBINARY="${BINARY}"; LogText " Found known binary: bootctl (systemd-boot manager utility) - ${BINARY}" ;;
bro) BROBINARY="${BINARY}"; LogText " Found known binary: bro (IDS) - ${BINARY}" ;;
cat) CAT_BINARY="${BINARY}"; LogText " Found known binary: cat (generic file handling) - ${BINARY}" ;;
cc) CCBINARY="${BINARY}"; COMPILER_INSTALLED=1; LogText " Found known binary: cc (compiler) - ${BINARY}" ;;
chkconfig) CHKCONFIGBINARY=${BINARY}; LogText " Found known binary: chkconfig (administration tool) - ${BINARY}" ;;
@ -131,7 +154,8 @@
domainname) DOMAINNAMEBINARY="${BINARY}"; LogText " Found known binary: domainname (NIS domain) - ${BINARY}" ;;
dpkg) DPKGBINARY="${BINARY}"; LogText " Found known binary: dpkg (package management) - ${BINARY}" ;;
egrep) EGREPBINARY=${BINARY}; LogText " Found known binary: egrep (text search) - ${BINARY}" ;;
exim) EXIMBINARY="${BINARY}"; EXIMVERSION=$(${BINARY} -bV | grep 'Exim version' | awk '{ print $3 }' | xargs); LogText "Found ${BINARY} (version ${EXIMVERSION})" ;;
equery) EQUERYBINARY="${BINARY}"; LogText " Found known binary: query (package manager) - ${BINARY}" ;;
exim) EXIMBINARY="${BINARY}"; EXIMVERSION=$(${BINARY} -bV | grep 'Exim version' | awk '{ print $3 }' | xargs); LogText " Found known binary ${BINARY} (version ${EXIMVERSION})" ;;
fail2ban-server) FAIL2BANBINARY="${BINARY}"; LogText " Found known binary: fail2ban (IPS tool) - ${BINARY}" ;;
file) FILEBINARY="${BINARY}"; LogText " Found known binary: file (file type detection) - ${BINARY}" ;;
find) FINDBINARY="${BINARY}"; LogText " Found known binary: find (search tool) - ${BINARY}" ;;
@ -164,7 +188,7 @@
lsattr) LSATTRBINARY="${BINARY}"; LogText " Found known binary: lsattr (file attributes) - ${BINARY}" ;;
lsmod) LSMODBINARY="${BINARY}"; LogText " Found known binary: lsmod (kernel modules) - ${BINARY}" ;;
lsof) LSOFBINARY="${BINARY}"; LogText " Found known binary: lsof (open files) - ${BINARY}" ;;
lsvg) LVSGBINARY=${BINARY}; LogText " Found known binary: lsvg (volume manager) - ${BINARY}" ;;
lsvg) LSVGBINARY=${BINARY}; LogText " Found known binary: lsvg (volume manager) - ${BINARY}" ;;
lvdisplay) LVDISPLAYBINARY="${BINARY}"; LogText " Found known binary: lvdisplay (LVM tool) - ${BINARY}" ;;
lynx) LYNXBINARY="${BINARY}"; LYNXVERSION=$(${BINARY} -version | grep "^Lynx Version" | cut -d ' ' -f3); LogText "Found known binary: lynx (browser) - ${BINARY} (version ${LYNXVERSION})" ;;
maldet) LMDBINARY="${BINARY}"; MALWARE_SCANNER_INSTALLED=1; LogText " Found known binary: maldet (Linux Malware Detect, malware scanner) - ${BINARY}" ;;
@ -225,6 +249,7 @@
sha1|sha1sum|shasum) SHA1SUMBINARY="${BINARY}"; LogText " Found known binary: sha1/sha1sum/shasum (crypto hashing) - ${BINARY}" ;;
sha256|sha256sum) SHA256SUMBINARY="${BINARY}"; LogText " Found known binary: sha256/sha256sum (crypto hashing) - ${BINARY}" ;;
ssh-keyscan) SSHKEYSCANBINARY="${BINARY}"; LogText " Found known binary: ssh-keyscan (scanner for SSH keys) - ${BINARY}" ;;
suricata) SURICATABINARY="${BINARY}"; LogText " Found known binary: suricata (IDS) - ${BINARY}" ;;
sysctl) SYSCTLBINARY="${BINARY}"; LogText " Found known binary: sysctl (kernel parameters) - ${BINARY}" ;;
syslog-ng) SYSLOGNGBINARY="${BINARY}"; SYSLOGNGVERSION=$(${BINARY} -V 2>&1 | grep "^syslog-ng" | awk '{ print $2 }'); LogText "Found ${BINARY} (version ${SYSLOGNGVERSION})" ;;
systemctl) SYSTEMCTLBINARY="${BINARY}"; LogText " Found known binary: systemctl (client to systemd) - ${BINARY}" ;;
@ -254,6 +279,7 @@
LogText "Result: Directory ${SCANDIR} does NOT exist"
fi
done
# unset SORTED_BIN_PATHS
BINARY_SCAN_FINISHED=1
BINARY_PATHS_FOUND=$(echo ${BINARY_PATHS_FOUND} | sed 's/^, //g' | sed 's/ //g')
@ -261,10 +287,35 @@
LogText "Result: found ${COUNT} binaries"
Report "binaries_count=${COUNT}"
Report "binary_paths=${BINARY_PATHS_FOUND}"
# Test if the basic system tools are defined. These will be used during the audit.
[ "${AWKBINARY:-}" ] || ExitFatal "awk binary not found"
[ "${CUTBINARY:-}" ] || ExitFatal "cut binary not found"
[ "${EGREPBINARY:-}" ] || ExitFatal "grep binary not found"
[ "${FINDBINARY:-}" ] || ExitFatal "find binary not found"
[ "${GREPBINARY:-}" ] || ExitFatal "grep binary not found"
[ "${HEADBINARY:-}" ] || ExitFatal "head binary not found"
[ "${LSBINARY:-}" ] || ExitFatal "ls binary not found"
[ "${PSBINARY:-}" ] || ExitFatal "ps binary not found"
[ "${SEDBINARY:-}" ] || ExitFatal "sed binary not found"
[ "${SORTBINARY:-}" ] || ExitFatal "sort binary not found"
[ "${TRBINARY:-}" ] || ExitFatal "tr binary not found"
[ "${UNIQBINARY:-}" ] || ExitFatal "uniq binary not found"
[ "${WCBINARY:-}" ] || ExitFatal "wc binary not found"
# Test a few other tools that we did not specifically define (yet)
TOOLS="xxd"
for T in ${TOOLS}; do
DATA=$(type ${T})
if [ $? -gt 0 ]; then ExitFatal "${T} binary not found"; fi
done
else
LogText "Result: checking of binaries skipped in this mode"
fi
#
#================================================================================
# Lynis - Security Auditing and System Hardening for Linux and UNIX - https://cisofy.com

View File

@ -46,6 +46,7 @@ unset LANG
#
# == Variable initializing ==
#
APTBINARY=""
ARCH_AUDIT_BINARY=""
AUDITORNAME=""
AUDITCTLBINARY=""
@ -70,6 +71,7 @@ unset LANG
CHKCONFIGBINARY=""
CLAMCONF_BINARY=""
CLAMSCANBINARY=""
CLANGBINARY=""
COLORS=1
COMPLIANCE_ENABLE_CIS=0
COMPLIANCE_ENABLE_HIPAA=0
@ -84,6 +86,7 @@ unset LANG
CONTAINER_TYPE=""
CREATE_REPORT_FILE=1
CSUMBINARY=""
CURRENT_TS=0
CUSTOM_URL_APPEND=""
CUSTOM_URL_PREPEND=""
CUSTOM_URL_PROTOCOL=""
@ -94,13 +97,17 @@ unset LANG
DEBSECANBINARY=""
DEBSUMSBINARY=""
DEVELOPER_MODE=0
DISABLED_PLUGINS=""
DISCOVERED_BINARIES=""
DMIDECODEBINARY=""
DNFBINARY=""
DOCKERBINARY=""
DOCKER_DAEMON_RUNNING=0
DPKGBINARY=""
ECHOCMD=""
ERROR_ON_WARNINGS=0
EQUERYBINARY=""
EXIMBINARY=""
FAIL2BANBINARY=""
FILEBINARY=""
FILEVALUE=""
@ -210,6 +217,8 @@ unset LANG
PLUGIN_PHASE=0
POSTFIXBINARY=""
POSTGRES_RUNNING=0
PREVIOUS_TEST="No test ID"
PREVIOUS_TS=0
PRIVILEGED=0
PROFILES=""
PROFILEVALUE=""
@ -248,8 +257,10 @@ unset LANG
SHOW_REPORT_SOLUTION=1
SHOW_TOOL_TIPS=1 # Show inline tool tips (default true)
SHOW_WARNINGS_ONLY=0
SKIP_GETHOSTID=0
SKIP_PLUGINS=0
SKIP_TESTS=""
SKIP_VM_DETECTION=0
SKIPREASON=""
SKIPPED_TESTS_ROOTONLY=""
SMTPCTLBINARY=""
@ -257,6 +268,7 @@ unset LANG
SSHKEYSCANBINARY=""
SSHKEYSCANFOUND=0
SSL_CERTIFICATE_PATHS=""
SSL_CERTIFICATE_PATHS_TO_IGNORE=""
STUNNELBINARY=""
SYSLOGNGBINARY=""
SYSTEMCTLBINARY=""
@ -270,6 +282,7 @@ unset LANG
TESTS_EXECUTED=""
TESTS_SKIPPED=""
TMPFILE=""
TOMOYOINITBINARY=""
TOOLTIP_SHOWED=0
TOTAL_SUGGESTIONS=0
TOTAL_WARNINGS=0
@ -340,7 +353,8 @@ unset LANG
#################################################################################
#
# Normal color names
# Normal color names (BG will color background)
BG_BLUE="$(printf '\033[0;44m')"
CYAN="$(printf '\033[0;36m')"
BLUE="$(printf '\033[0;34m')"
BROWN="$(printf '\033[0;33m')"
@ -354,15 +368,13 @@ unset LANG
YELLOW="$(printf '\033[1;33m')"
WHITE="$(printf '\033[1;37m')"
# Markup
# Special markup
BOLD="${WHITE}"
# With background
BG_BLUE="$(printf '\033[0;44m')"
NORMAL="$(printf '\033[0m')"
# Semantic names
BG_WARNING="$(printf '\033[30;43m')" # Yellow background with grey text
HEADER="${WHITE}"
NORMAL="$(printf '\033[0m')"
WARNING="${RED}"
SECTION="${YELLOW}"
NOTICE="${YELLOW}"

View File

@ -242,13 +242,9 @@
fi
else
echo "${RED}Error${NORMAL}: No hostid and/or hostid2 found. Can not upload report file."
echo "Suggested command: lynis show hostids"
echo "Suggested command: lynis generate hostids --save"
echo ""
echo "If hostid2 is the only ID that is missing, use the following step:"
echo "Create hash and add it to custom.prf"
echo "echo \"hostid2=\$(cat /dev/urandom | tr -dc 'a-f0-9' | fold -w 64 | head -n 1)\" >> /etc/lynis/custom.prf"
echo ""
echo "Note: do not replicate this ID to other systems, as it needs to be unique per system"
echo "Note: do not replicate the values to other systems, as it needs to be unique per system"
# Quit
ExitFatal

View File

@ -42,6 +42,8 @@
# DisplayError Show an error on screen
# DisplayManual Output text to screen without any layout
# DisplayToolTip Show a tip for improving usage of the tool
# DisplayWarning Show a clear warning on screen
# Equals Compares two strings
# ExitClean Stop the program (cleanly), with exit code 0
# ExitCustom Stop the program (cleanly), with custom exit code
# ExitFatal Stop the program (cleanly), with exit code 1
@ -74,6 +76,7 @@
# ParseTestValues Parse a set of values
# PortIsListening Check if machine is listening on specified protocol and port
# Progress Show progress on screen
# Readonly Mark a variable as read-only data
# Register Register a test (for logging and execution)
# RandomString Show a random string
# RemoveColors Reset all colors
@ -85,7 +88,9 @@
# ReportManual Log manual actions to report file
# ReportSuggestion Add a suggestion to report file
# ReportWarning Add a warning and priority to report file
# SafeFile Security tests to perform on a file before using it
# SafePerms Check if a file has safe permissions
# SafeInput Test provided string to see if it contains unwanted characters
# SearchItem Search a string in a file
# ShowComplianceFinding Display a particular finding regarding compliance or a security standard
# ShowSymlinkPath Show a path behind a symlink
@ -114,7 +119,8 @@
# Name : AddHP()
# Description : Add hardening points and count them
#
# Input : $1 = points to add, $2 = maximum points for this item
# Parameters : $1 = points to add (0 or higher)
# $2 = maximum points (at least value of $1 or higher)
# Returns : <nothing>
# Usage : AddHP 1 3
################################################################################
@ -135,7 +141,9 @@
# Name : AddSetting()
# Description : Addition of a setting for display with 'lynis show settings'
#
# Input : $1 = setting, $2 = value, $3 description
# Parameters : $1 = setting
# $2 = value
# $3 = description
# Returns : <nothing>
# Usage : AddSetting debug 1 'Debug mode'
################################################################################
@ -159,7 +167,7 @@
TEMP_SETTINGS_FILE="${TEMP_FILE}"
cat ${SETTINGS_FILE} > ${TEMP_SETTINGS_FILE}
sed -e '/^'"${SETTING}"';/d' ${TEMP_SETTINGS_FILE} > ${SETTINGS_FILE}
rm ${TEMP_SETTINGS_FILE}
rm "${TEMP_SETTINGS_FILE}"
echo "${SETTING};${VALUE};${DESCRIPTION};" >> ${SETTINGS_FILE}
fi
else
@ -172,7 +180,7 @@
# Name : AddSystemGroup()
# Description : Adds a system to a group, which can be used for categorizing
#
# Input : Group name
# Parameters : $1 = group name
# Returns : <nothing>
# Usage : AddSystemGroup "test"
################################################################################
@ -186,13 +194,13 @@
# Name : CheckFilePermissions()
# Description : Check file permissions
#
# Input : full path to file or directory
# Parameters : Full path to file or directory
# Returns : PERMS (FILE_NOT_FOUND | OK | BAD)
# Notes : This function might be replaced in future
################################################################################
CheckFilePermissions() {
CHECKFILE=$1
CHECKFILE="$1"
if [ ! -d ${CHECKFILE} -a ! -f ${CHECKFILE} ]; then
PERMS="FILE_NOT_FOUND"
else
@ -213,13 +221,13 @@
# Name : CheckItem()
# Description : Check if a specific item exists in the report
#
# Input : $1 = key, $2 = value
# Returns : ITEM_FOUND
# Usage : CheckItem "key" "value"
# Parameters : $1 = key
# $2 = value
# Returns : True (0) or False (1)
# Usage : if CheckItem "key" "value"; then ....; fi
################################################################################
CheckItem() {
ITEM_FOUND=0
RETVAL=255
if [ $# -eq 2 ]; then
# Don't search in /dev/null, it's too empty there
@ -228,7 +236,6 @@
LogText "Test: search string $2 in earlier discovered results"
FIND=$(egrep "^$1(\[\])?=" ${REPORTFILE} | egrep "$2")
if HasData "${FIND}"; then
ITEM_FOUND=1
RETVAL=0
LogText "Result: found search string (result: $FIND)"
else
@ -248,6 +255,7 @@
################################################################################
# Name : CheckUpdates()
# Description : Determine if there is an update available
#
# Returns : <nothing>
# Usage : CheckUpdates
# Use PROGRAM_LV (latest version) and compare it with actual version (PROGRAM_AC)
@ -282,8 +290,9 @@
################################################################################
# Name : CleanUp()
# Description : Cleanup service
# Returns : <nothing>
# Description : Delete PID and temporary files, stop execution (exit code 1)
#
# Usage : this function is triggered by a manual break by user
################################################################################
CleanUp() {
@ -298,7 +307,8 @@
################################################################################
# Name : ContainsString()
# Description : Search a specific string (or regular expression) in another
# Returns : (0 - True, 1 - False)
#
# Returns : True (0) or False (1)
# Usage : if ContainsString "needle" "there is a needle in the haystack"; echo "Found"; else "Not found"; fi
################################################################################
@ -313,11 +323,9 @@
################################################################################
# Name : CountTests()
# Description : Count the number of tests performed
# Description : Counter for the number of tests performed
#
# Input : <nothing>
# Returns : <nothing>
# Usage : CountTests
# Usage : Call CountTests to increase number by 1
################################################################################
CountTests() {
@ -329,7 +337,6 @@
# Name : CreateTempFile()
# Description : Creates a temporary file
#
# Input : <nothing>
# Returns : TEMP_FILE (variable)
# Usage : CreateTempFile
# if [ ! "${TEMP_FILE}" = "" ]; then
@ -361,7 +368,7 @@
# Name : DirectoryExists()
# Description : Check if a directory exists
#
# Returns : 0 (directory exists), 1 (directory does not exist)
# Returns : True (0) or False (1)
# Usage : if DirectoryExists; then echo "it exists"; else echo "It does not exist"; fi
################################################################################
@ -605,6 +612,46 @@
}
################################################################################
# Name : DisplayWarning
# Description : Show a warning on the screen
#
# Input : $1 = text
# Returns : <nothing>
################################################################################
DisplayWarning() {
if [ ${CRONJOB} -eq 0 ]; then
printf "\n"
${ECHOCMD:-echo} " ${BG_WARNING}[WARNING]${NORMAL}: $1${NORMAL}"
printf "\n"
else
${ECHOCMD} " [WARNING]: $1"
fi
}
################################################################################
# Name : Equals()
# Description : Compare two strings
#
# Returns : (0 - True, 1 - False)
# Usage : if Equals "${MYDIR}" "/etc"; then echo "Found"; else "Not found"; fi
################################################################################
Equals() {
RETVAL=1
if [ $# -ne 2 ]; then ReportException "Equals" "Incorrect number of arguments for $0 function"; fi
# Strip any strange control characters
INPUT1=$(echo $1 | tr -d '[:cntrl:]<>' | ${SEDBINARY} 's/__space__/ /g' | ${SEDBINARY} 's/:space:/ /g')
INPUT2=$(echo $2 | tr -d '[:cntrl:]<>' | ${SEDBINARY} 's/__space__/ /g' | ${SEDBINARY} 's/:space:/ /g')
if [ "${INPUT1}" = "${INPUT2}" ]; then RETVAL=0; fi
return ${RETVAL}
}
################################################################################
# Name : ExitClean()
# Description : Perform a normal exit of the program, and clean up resources
@ -659,9 +706,9 @@
RemoveTempFiles
LogText "${PROGRAM_NAME} ended with exit code 1."
if [ $# -eq 1 ]; then
${ECHOCMD} ""
${ECHOCMD} "${RED}Fatal error${NORMAL}: ${WHITE}$1${NORMAL}"
${ECHOCMD} ""
${ECHOCMD:-echo} ""
${ECHOCMD:-echo} "${RED}Fatal error${NORMAL}: ${WHITE}$1${NORMAL}"
${ECHOCMD:-echo} ""
fi
exit 1
}
@ -805,15 +852,26 @@
# Name : GetHostID()
# Description : Create an unique id for the system
#
# Returns : optional value
# Returns : 0 = fetched or created IDs, 1 = failed, 2 = skipped
# Usage : GetHostID
################################################################################
GetHostID() {
if [ ${SKIP_GETHOSTID} -eq 1 ]; then
return 2
fi
if [ ! -z "${HOSTID}" -a ! -z "${HOSTID2}" ]; then
Debug "Skipping creation of host identifiers, as they are already configured (via profile)"
return 1
return 2
fi
if [ -f "${ROOTDIR}etc/lynis/hostids" ]; then
Debug "Used hostids file to fetch values"
HOSTID=$(grep "^hostid=" ${ROOTDIR}etc/lynis/hostids | awk -F= '{print $2}')
HOSTID2=$(grep "^hostid2=" ${ROOTDIR}etc/lynis/hostids | awk -F= '{print $2}')
return 0
fi
FIND=""
@ -1110,8 +1168,9 @@
fi
# Show an exception if no HostID could be created, to ensure each system (and scan) has one
if [ "${HOSTID}" = "" ]; then
if [ -z "${HOSTID}" ]; then
ReportException "GetHostID" "No unique host identifier could be created."
return 1
elif [ ! -z "${HOSTID2}" ]; then
return 0
fi
@ -1284,7 +1343,8 @@
if [ -z "${search}" ]; then ExitFatal "Missing process to search for when using IsRunning function"; fi
RUNNING=0
if [ ! -z "${PGREPBINARY}" ]; then
# AIX does not fully support pgrep options, so using ps instead
if [ ! -z "${PGREPBINARY}" -a ! "${OS}" = "AIX" ]; then
FIND=$(${PGREPBINARY} ${pgrep_options} "${search}" | ${TRBINARY} '\n' ' ')
else
if [ -z "${PSOPTIONS}" ]; then
@ -1392,6 +1452,10 @@
ISVIRTUALMACHINE=2; VMTYPE="unknown"; VMFULLTYPE="Unknown"
SHORT=""
if [ ${SKIP_VM_DETECTION} -eq 1 ]; then
return 2
fi
# lxc environ detection
if [ -z "${SHORT}" ]; then
if [ -f /proc/1/environ ]; then
@ -1699,7 +1763,7 @@
################################################################################
# Name : PackageIsInstalled()
# Description : Add a separator to log file between sections, tests etc
# Description : Determines if a package is installed
# Returns : exit code
# Notes : this function is not used yet, but created in advance to allow
# the addition of support for all operating systems
@ -1714,11 +1778,20 @@
Fatal "Incorrect usage of PackageIsInstalled function"
fi
if [ ! -z "${RPMBINARY}" ]; then
output=$(${RPMBINARY} --quiet -q ${package} 2> /dev/null)
if [ ! -z "${DNFBINARY}" ]; then
output=$(${DNFBINARY} --quiet --cacheonly --noplugins --assumeno info --installed ${package} > /dev/null 2>&1)
exit_code=$?
elif ! -z "${DPKGBINARY}" ]; then
output=$(${DPKGBINARY} -l ${package} 2> /dev/null)
elif [ ! -z "${DPKGBINARY}" ]; then
output=$(${DPKGBINARY} -l ${package} 2> /dev/null | ${GREPBINARY} "^ii")
exit_code=$?
elif [ ! -z "${EQUERYBINARY}" ]; then
output=$(${EQUERYBINARY} --quiet ${package} > /dev/null 2>&1)
exit_code=$? # 0=package installed, 3=package not installed
elif [ ! -z "${PKG_BINARY}" ]; then
output=$(${PKG_BINARY} -N info ${package} >/dev/null 2>&1)
exit_code=$? # 0=package installed, 70=invalid package
elif [ ! -z "${RPMBINARY}" ]; then
output=$(${RPMBINARY} --quiet -q ${package} > /dev/null 2>&1)
exit_code=$?
elif [ ! -z "${ZYPPERBINARY}" ]; then
output=$(${ZYPPERBINARY} --quiet --non-interactive search --installed -i ${PACKAGE} 2> /dev/null | grep "^i")
@ -1983,7 +2056,7 @@
for ITEM in ${VALUE}; do
LogText "Result: found protocol ${ITEM}"
case ${ITEM} in
"sslv2" | "sslv3")
"sslv2" | "sslv3" | "tlsv1")
NGINX_WEAK_SSL_PROTOCOL_FOUND=1
;;
esac
@ -2089,6 +2162,24 @@
}
################################################################################
# Name : Readonly()
# Description : Mark a variable as read-only data
# Returns : nothing
################################################################################
Readonly() {
if [ $# -eq 1 ]; then
if type -t typeset; then
typeset -r $1
else
Debug "No typeset available to mark variable '$1' as read-only variable"
fi
else
ExitFatal "Expected 1 parameter, received none or multiple"
fi
}
################################################################################
# Name : Register()
@ -2096,6 +2187,19 @@
# Returns : SKIPTEST (0 or 1)
################################################################################
GetTimestamp() {
ts=0
case "${OS}" in
"Linux")
ts=$(date "+%s%N")
;;
*)
ts=$(date "+%s")
;;
esac
echo $ts
}
Register() {
# Do not insert a log break, if previous test was not logged
if [ ${SKIPLOGTEST} -eq 0 ]; then LogTextBreak; fi
@ -2163,6 +2267,35 @@
shift
done
# Measure timing
CURRENT_TS=$(GetTimestamp)
if [ ${PREVIOUS_TS} -gt 0 ]; then
SLOW_TEST=0
TIME_THRESHOLD=10 # seconds
# Calculate timing and determine if we use seconds or nanoseconds (more precise)
TIME_DIFF=$((${CURRENT_TS} - ${PREVIOUS_TS}))
if [ ${CURRENT_TS} -gt 1000000000000000000 ]; then
TIME_DIFF_FORMAT="nanoseconds"
TIME_THRESHOLD=$((${TIME_THRESHOLD} * 1000000000))
if [ ${TIME_DIFF} -gt ${TIME_THRESHOLD} ]; then
SLOW_TEST=1
# Convert back to seconds for readability
TIME_DIFF_FORMAT="seconds"
TIME_DIFF=$(echo ${TIME_DIFF} | ${AWKBINARY} '{printf "%f",$1/1000000000}')
fi
else
TIME_DIFF_FORMAT="seconds"
if [ ${TIME_DIFF} -gt ${TIME_THRESHOLD} ]; then
SLOW_TEST=1
fi
fi
if [ ${SLOW_TEST} -eq 1 ]; then
DisplayWarning "Test ${PREVIOUS_TEST} had a long execution: ${TIME_DIFF} ${TIME_DIFF_FORMAT}"
Report "slow_test[]=${PREVIOUS_TEST},${TIME_DIFF}"
fi
fi
# Skip test if it's configured in profile (old style)
if [ ${SKIPTEST} -eq 0 ]; then
FIND=$(echo "${TEST_SKIP_ALWAYS}" | grep "${TEST_NO}" | tr '[:lower:]' '[:upper:]')
@ -2235,6 +2368,10 @@
TESTS_SKIPPED="${TEST_NO}|${TESTS_SKIPPED}"
fi
unset SKIPREASON
# Save timestamp for next time the Register function is called
PREVIOUS_TEST="${TEST_NO}"
PREVIOUS_TS="${CURRENT_TS}"
}
@ -2262,6 +2399,7 @@
# Colors with background
BG_BLUE=""
BG_WARNING=""
# Semantic names
BAD=""
@ -2276,14 +2414,15 @@
################################################################################
# Name : RemovePIDFile()
# Description : When defined, remove the file storing the process ID
################################################################################
# Remove PID file
RemovePIDFile() {
# Test if PIDFILE is defined, before checking file presence
if [ ! "${PIDFILE}" = "" ]; then
if [ -f ${PIDFILE} ]; then
rm -f $PIDFILE;
if [ ! -z "${PIDFILE}" ]; then
if [ -f "${PIDFILE}" ]; then
rm -f "${PIDFILE}"
LogText "PID file removed (${PIDFILE})"
else
LogText "PID file not found (${PIDFILE})"
@ -2294,6 +2433,7 @@
################################################################################
# Name : RemoveTempFiles()
# Description : When created, delete any temporary file
################################################################################
# Remove any temporary files
@ -2304,10 +2444,10 @@
for FILE in ${TEMP_FILES}; do
# Temporary files should be in /tmp
TMPFILE=$(echo ${FILE} | egrep "^/tmp/lynis" | grep -v "\.\.")
if [ ! "${TMPFILE}" = "" ]; then
if [ -f ${TMPFILE} ]; then
if [ ! -z "${TMPFILE}" ]; then
if [ -f "${TMPFILE}" ]; then
LogText "Action: removing temporary file ${TMPFILE}"
rm -f ${TMPFILE}
rm -f "${TMPFILE}"
else
LogText "Info: temporary file ${TMPFILE} was already removed"
fi
@ -2323,6 +2463,7 @@
################################################################################
# Name : Report()
# Description : Store data in the report file
################################################################################
Report() {
@ -2397,12 +2538,14 @@
################################################################################
# Name : ReportException()
# Description : Store an exceptional event in the report
#
# Parameters : $1 = test ID + colon + 2 numeric characters (TEST-1234:01)
# $2 = string (text)
################################################################################
# Log exceptions
ReportException() {
# 1 parameters
# <ID>:<2 char numeric>|text|
Report "exception_event[]=$1|$2|"
LogText "Exception: test has an exceptional event ($1) with text $2"
}
@ -2410,11 +2553,12 @@
################################################################################
# Name : ReportManual()
# Description : Add an item to the report that requires manual intervention
#
# Parameters : $1 = string (text)
################################################################################
# Log manual actions to report file
ReportManual() {
# 1 parameter: Text
Report "manual_event[]=$1"
LogText "Manual: one or more manual actions are required for further testing of this control/plugin"
}
@ -2422,20 +2566,20 @@
################################################################################
# Name : ReportSuggestion()
# Description : Log a suggestion to the report file
#
# Parameters : <ID> <Suggestion> <Details> <Solution>
# $1 = Test ID - Lynis ID (use CUST-.... for your own tests)
# $2 = Suggestion - Suggestion text to be displayed
# $3 = Details - Specific item or details
# $4 = Solution - Optional link for additional information:
# * url:https://example.org/how-to-solve-link
# * text:Additional explanation
# * - (dash) for none
################################################################################
# Log suggestions to report file
ReportSuggestion() {
TOTAL_SUGGESTIONS=$((TOTAL_SUGGESTIONS + 1))
# 4 parameters
# <ID> <Suggestion> <Details> <Solution>
# <ID> Lynis ID (use CUST-.... for your own tests)
# <Suggestion> Suggestion text to be displayed
# <Details> Specific item or details
# <Solution> Optional link for additional information:
# * url:http://site/link
# * text:Additional explanation
# * - for none
if [ $# -eq 0 ]; then echo "Not enough arguments provided for function ReportSuggestion"; ExitFatal; fi
if [ $# -ge 1 ]; then TEST="$1"; else TEST="UNKNOWN"; fi
if [ $# -ge 2 ]; then MESSAGE="$2"; else MESSAGE="UNKNOWN"; fi
@ -2449,9 +2593,9 @@
################################################################################
# Name : ReportWarning()
# Description : Log a warning to the report file
################################################################################
# Log warning to report file
ReportWarning() {
TOTAL_WARNINGS=$((TOTAL_WARNINGS + 1))
# Old style
@ -2484,76 +2628,180 @@
}
################################################################################
# Name : SafeInput()
# Description : Test provided string to see if it contains unwanted characters
#
# Input : string + optional class (parameter 2)
# Returns : 0 (input considered to be safe) or 1 (validation failed)
################################################################################
SafeInput() {
exitcode=1
# By default remove only control characters
if [ $# -eq 1 ]; then
input="$1"
cleaned=$(echo ${input} | tr -d '[:cntrl:]')
# If know what to test against, then see if input matches the specified class
elif [ $# -eq 2 ]; then
input="$1"
testchars="$2"
cleaned=$(echo $1 | tr -cd "${testchars}")
else
ExitFatal "No argument or too many arguments provided to SafeInput()"
fi
if [ "${cleaned}" = "${input}" ]; then
exitcode=0
fi
return ${exitcode}
}
################################################################################
# Name : SafeFile()
# Description : Check if a file is safe to use
#
################################################################################
SafeFile() {
unsafe=0
if [ $# -ne 1 ]; then
ExitFatal "No argument or too many arguments provided to SafeFile()"
else
FILE="$1"
# Generic checks
if [ -g "${FILE}" ]; then
LogText "Security alert: file has setgid attribute"
unsafe=1
# sticky bit
elif [ -k "${FILE}" ]; then
LogText "Security alert: file has sticky bit"
unsafe=1
# symbolic link
elif [ -L "${FILE}" ]; then
LogText "Security alert: file is a symbolic link"
unsafe=1
elif [ -f "${FILE}" ]; then
LogText "Security check: file is normal"
else
unsafe=1
fi
# Perform additional checks based on privilege level
if [ ${PRIVILEGED} -eq 0 ]; then
# File is not owned by active user, but still able to write
if [ ! -O "${FILE}" -a -w "${FILE}" ]; then
unsafe=1
LogText "Security alert: file is not owned by active user, but can write to it"
fi
fi
# Check file permissions
if ! SafePerms "${FILE}"; then
unsafe=1
fi
fi
return ${unsafe}
}
################################################################################
# Name : SafePerms()
# Return : 0 (file OK) or break
# Description : Check if a file has safe permissions to be used
#
# Returns : 0 (file permissions OK) or break
################################################################################
SafePerms() {
if [ ${WARN_ON_FILE_ISSUES} -eq 1 ]; then
exitcode=1
IS_PARAMETERS=0
IS_PROFILE=0
if [ ${IGNORE_FILE_PERMISSION_ISSUES} -eq 0 ]; then
PERMS_OK=0
LogText "Checking permissions of $1"
if [ $# -eq 1 ]; then
IS_PARAMETERS_FILE=$(echo $1 | grep "/parameters")
if [ $# -gt 0 ]; then
if [ $# -eq 2 ]; then
case "$2" in
"parameters")
IS_PARAMETERS=1
;;
"profile")
IS_PROFILE=1
;;
esac
else
FIND=$(echo $1 | grep "/parameters")
if [ $? -eq 0 ]; then IS_PARAMETERS=1; fi
fi
# Check file permissions
if [ ! -f "$1" ]; then
LogText "Fatal error: file $1 does not exist. Quitting."
echo "Fatal error: file $1 does not exist"
ExitFatal
else
PERMS=$(ls -l $1)
# Owner permissions
OWNER=$(echo ${PERMS} | awk -F" " '{ print $3 }')
OWNERID=$(ls -n $1 | awk -F" " '{ print $3 }')
if [ ${PENTESTINGMODE} -eq 0 -a "${IS_PARAMETERS_FILE}" = "" ]; then
if [ ! "${OWNER}" = "root" -a ! "${OWNERID}" = "0" ]; then
echo "Fatal error: file $1 should be owned by user 'root' when running it as root (found: ${OWNER})."
ExitFatal
fi
fi
# Group permissions
GROUP=$(echo ${PERMS} | awk -F" " '{ print $4 }')
GROUPID=$(ls -n $1 | awk -F" " '{ print $4 }')
if [ ! -f "$1" ]; then
LogText "Fatal error: file $1 does not exist. Quitting."
echo "Fatal error: file $1 does not exist"
ExitFatal
else
PERMS=$(ls -l $1)
if [ ${PENTESTINGMODE} -eq 0 -a "${IS_PARAMETERS_FILE}" = "" ]; then
if [ ! "${GROUP}" = "root" -a ! "${GROUP}" = "wheel" -a ! "${GROUPID}" = "0" ]; then
echo "Fatal error: group owner of directory $1 should be owned by root user, wheel or similar (found: ${GROUP})."
ExitFatal
fi
fi
# Owner permissions
OWNER=$(echo ${PERMS} | awk -F" " '{ print $3 }')
OWNERID=$(ls -n $1 | awk -F" " '{ print $3 }')
if [ ${PENTESTINGMODE} -eq 0 -a ${IS_PARAMETERS} -eq 0 ]; then
if [ ! "${OWNER}" = "root" -a ! "${OWNERID}" = "0" ]; then
echo "Fatal error: file $1 should be owned by user 'root' when running it as root (found: ${OWNER})."
ExitFatal
fi
fi
# Group permissions
GROUP=$(echo ${PERMS} | awk -F" " '{ print $4 }')
GROUPID=$(ls -n $1 | awk -F" " '{ print $4 }')
# Owner permissions
OWNER_PERMS=$(echo ${PERMS} | cut -c2-4)
if [ ! "${OWNER_PERMS}" = "rw-" -a ! "${OWNER_PERMS}" = "r--" ]; then
echo "Fatal error: permissions of file $1 are not strict enough. Access to 'owner' should be read-write, or read. Change with: chmod 600 $1"
ExitFatal
fi
if [ ${PENTESTINGMODE} -eq 0 -a ${IS_PARAMETERS} -eq 0 ]; then
if [ ! "${GROUP}" = "root" -a ! "${GROUP}" = "wheel" -a ! "${GROUPID}" = "0" ]; then
echo "Fatal error: group owner of directory $1 should be owned by root user, wheel or similar (found: ${GROUP})."
ExitFatal
fi
fi
# Owner permissions
GROUP_PERMS=$(echo ${PERMS} | cut -c5-7)
if [ ! "${GROUP_PERMS}" = "rw-" -a ! "${GROUP_PERMS}" = "r--" -a ! "${GROUP_PERMS}" = "---" ]; then
echo "Fatal error: permissions of file $1 are not strict enough. Access to 'group' should be read-write, read, or none. Change with: chmod 600 $1"
ExitFatal
fi
# Owner permissions
OWNER_PERMS=$(echo ${PERMS} | cut -c2-4)
if [ ! "${OWNER_PERMS}" = "rw-" -a ! "${OWNER_PERMS}" = "r--" ]; then
echo "Fatal error: permissions of file $1 are not strict enough. Access to 'owner' should be read-write, or read. Change with: chmod 600 $1"
ExitFatal
fi
# Other permissions
OTHER_PERMS=$(echo ${PERMS} | cut -c8-10)
if [ ! "${OTHER_PERMS}" = "---" -a ! "${OTHER_PERMS}" = "r--" ]; then
echo "Fatal error: permissions of file $1 are not strict enough. Access to 'other' should be denied or read-only. Change with: chmod 600 $1"
ExitFatal
fi
# Set PERMS_OK to 1 if no fatal errors occurred
PERMS_OK=1
LogText "File permissions are OK"
return 0
fi
# Owner permissions
GROUP_PERMS=$(echo ${PERMS} | cut -c5-7)
if [ ! "${GROUP_PERMS}" = "rw-" -a ! "${GROUP_PERMS}" = "r--" -a ! "${GROUP_PERMS}" = "---" ]; then
echo "Fatal error: permissions of file $1 are not strict enough. Access to 'group' should be read-write, read, or none. Change with: chmod 600 $1"
ExitFatal
fi
# Other permissions
OTHER_PERMS=$(echo ${PERMS} | cut -c8-10)
if [ ! "${OTHER_PERMS}" = "---" -a ! "${OTHER_PERMS}" = "r--" ]; then
echo "Fatal error: permissions of file $1 are not strict enough. Access to 'other' should be denied or read-only. Change with: chmod 600 $1"
ExitFatal
fi
# Set PERMS_OK to 1 if no fatal errors occurred
PERMS_OK=1
LogText "File permissions are OK"
exitcode=0
fi
else
ReportException "SafePerms()" "Invalid number of arguments for function"
fi
else
PERMS_OK=1
return 0
exitcode=0
fi
return ${exitcode}
}
@ -2561,14 +2809,15 @@
# Name : SearchItem()
# Description : Search if a specific string exists in in a file
#
# Input : $1 = search key (string), $2 = file (string), $3 and later
# are optional arguments
# Parameters : $1 = search key (string)
# $2 = file (string)
# $3 = optional arguments:
# --sensitive - don't store results in log
# Returns : True (0) or False (1)
################################################################################
SearchItem() {
PERFORM_SCAN=0
ITEM_FOUND=0
MASK_LOG=0
RETVAL=1
if [ $# -lt 2 ]; then
@ -2596,8 +2845,7 @@
# Check if we can find the main type (with or without brackets)
LogText "Test: search string ${STRING} in file ${FILE}"
FIND=$(egrep "${STRING}" ${FILE})
if [ ! "${FIND}" = "" ]; then
ITEM_FOUND=1
if [ ! -z "${FIND}" ]; then
LogText "Result: found search string '${STRING}'"
if [ ${MASK_LOG} -eq 0 ]; then LogText "Full string returned: ${FIND}"; fi
RETVAL=0
@ -2616,21 +2864,6 @@
}
# Show result code (to be removed)
ShowResult() {
case $1 in
OK)
echo "[ ${OK}OK${NORMAL} ]"
;;
WARNING)
echo "[ ${WARNING}WARNING${NORMAL} ]"
# log the warning to our log file
#LogText "Warning: $2"
# add the warning to our report file
#Report "warning=$2"
;;
esac
}
################################################################################
@ -3191,35 +3424,44 @@
#
################################################################################
# For compatibility reasons they are listed here, but will be phased out in
# steps. If they still get used, they will trigger an alert when using the
# developer mode. In a later phase they will trigger errors on screen.
# steps. If they still get used, they will trigger errors on screen.
################################################################################
counttests() {
DisplayWarning "Deprecated function used (counttests)"
if IsDeveloperMode; then Debug "Warning: old counttests function is used. Please replace any reference with CountTests."; fi
CountTests
}
logtext() {
DisplayWarning "Deprecated function used (logtext)"
if IsDeveloperMode; then Debug "Warning: old logtext function is used. Please replace any reference with LogText."; fi
LogText "$1"
}
logtextbreak() {
DisplayWarning "Deprecated function used (logtextbreak)"
if IsDeveloperMode; then Debug "Warning: old logtextbreak function is used. Please replace any reference with LogTextBreak."; fi
LogTextBreak "$1"
}
report() {
DisplayWarning "Deprecated function used (report)"
if IsDeveloperMode; then Debug "Warning: old report function is used. Please replace any reference with Report."; fi
Report "$1"
}
wait_for_keypress() {
DisplayWarning "Deprecated function used (wait_for_keypress)"
if IsDeveloperMode; then Debug "Warning: old wait_for_keypress function is used. Please replace any reference with WaitForKeyPress."; fi
WaitForKeyPress
}
ShowResult() {
DisplayWarning "Deprecated function used (ShowResult)"
if IsDeveloperMode; then Debug "Warning: old ShowResult() function is used. Please replace any reference with WaitForKeyPress."; fi
}
#================================================================================

View File

@ -19,25 +19,14 @@
#################################################################################
if [ $# -eq 0 ]; then
Display --indent 2 --text "${RED}Error: ${WHITE}Provide URL or file${NORMAL}"
Display --indent 2 --text "${RED}Error: ${WHITE}Provide a file${NORMAL}"
Display --text " "; Display --text " "
ExitFatal
else
FILE=$(echo $1 | egrep "^http|https")
if HasData "${FILE}"; then
CreateTempFile
TMP_FILE="${TEMP_FILE}"
Display --indent 2 --text "Downloading URL ${FILE} with wget"
wget -o ${TMP_FILE} ${FILE}
if [ $? -gt 0 ]; then
AUDIT_FILE="${TMP_FILE}"
else
if [ -f ${TMP_FILE} ]; then
rm -f ${TMP_FILE}
fi
Display --indent 2 --text "${RED}Error: ${WHITE}can not download file${NORMAL}"
ExitFatal
fi
echo "Provide a file (not a URL)"
ExitFatal
else
if [ -f $1 ]; then
AUDIT_FILE="$1"
@ -70,13 +59,12 @@ fi
IS_ALPINE=$(echo ${IMAGE} | grep -i alpine)
IS_LATEST=$(echo ${TAG} | grep -i latest)
if [ ! "${IS_DEBIAN}" = "" ]; then IMAGE="debian"; fi
if [ ! "${IS_FEDORA}" = "" ]; then IMAGE="fedora"; fi
if [ ! "${IS_UBUNTU}" = "" ]; then IMAGE="ubuntu"; fi
if [ ! "${IS_ALPINE}" = "" ]; then IMAGE="alpine"; fi
if [ ! "${IS_LATEST}" = "" ]; then
ReportWarning "dockerfile" "latest TAG used. Specifying the version is better."
if [ ! -z "${IS_DEBIAN}" ]; then IMAGE="debian"; fi
if [ ! -z "${IS_FEDORA}" ]; then IMAGE="fedora"; fi
if [ ! -z "${IS_UBUNTU}" ]; then IMAGE="ubuntu"; fi
if [ ! -z "${IS_ALPINE}" ]; then IMAGE="alpine"; fi
if [ ! -z "${IS_LATEST}" ]; then
ReportWarning "dockerfile" "latest TAG used. Specifying a targeted OS image and version is better for reproducible results."
fi
case ${IMAGE} in
@ -110,14 +98,14 @@ InsertSection "Basics"
#FIND=$(egrep "^MAINTAINER" ${AUDIT_FILE} | sed 's/ /:space:/g')
FIND=$(egrep -i "*MAINTAINER" ${AUDIT_FILE} | sed 's/=/ /g' | cut -d'"' -f 2)
if [ "${FIND}" = "" ]; then
if [ -z "${FIND}" ]; then
ReportWarning "dockerfile" "No maintainer found. Unclear who created this file."
else
#MAINTAINER=$(echo ${FIND} | sed 's/:space:/ /g' | awk '{ if($1=="MAINTAINER") { print }}')
MAINTAINER=$(echo ${FIND})
Display --indent 2 --text "Maintainer" --result "${MAINTAINER}"
fi
FIND=$(grep "^ENTRYPOINT" ${AUDIT_FILE} | cut -d' ' -f2 )
if [ "${FIND}" = "" ]; then
ReportWarning "dockerfile" "No ENTRYPOINT defined in Dockerfile."
@ -127,7 +115,7 @@ InsertSection "Basics"
fi
FIND=$(grep "^CMD" ${AUDIT_FILE} | cut -d' ' -f2 )
if [ "${FIND}" = "" ]; then
if [ -z "${FIND}" ]; then
ReportWarning "dockerfile" "No CMD defines in Dockerfile."
else
CMD=$(echo ${FIND})
@ -135,7 +123,7 @@ InsertSection "Basics"
fi
FIND=$(grep "^USER" ${AUDIT_FILE} | cut -d' ' -f2 )
if [ "${FIND}" = "" ]; then
if [ -z "${FIND}" ]; then
ReportWarning "dockerfile" "No user declared in Dockerfile. Container will execute command as root"
else
USER=$(echo ${FIND})

180
include/helper_generate Normal file
View File

@ -0,0 +1,180 @@
#!/bin/sh
#################################################################################
#
# Lynis
# ------------------
#
# Copyright 2007-2013, Michael Boelen
# Copyright 2007-2019, CISOfy
#
# Website : https://cisofy.com
# Blog : http://linux-audit.com
# GitHub : https://github.com/CISOfy/lynis
#
# Lynis comes with ABSOLUTELY NO WARRANTY. This is free software, and you are
# welcome to redistribute it under the terms of the GNU General Public License.
# See LICENSE file for usage of this software.
#
######################################################################
#
# Helper program to generate specific details such as host IDs
#
######################################################################
#
# How to use:
# ------------
# Run: lynis generate <option>
#
######################################################################
SAVEFILE=0
GENERATE_ARGS="hostids systemd-units"
if [ $# -gt 0 ]; then
case $1 in
"hostids")
if [ $# -gt 1 ]; then
shift
if [ $1 = "--save" ]; then
SAVEFILE=1
fi
fi
# Generate random host IDs
HOSTID=$(head -c20 < /dev/urandom | xxd -c 20 -p)
HOSTID2=$(head -c32 < /dev/urandom | xxd -c 32 -p)
${ECHOCMD} "Generated host identifiers"
${ECHOCMD} "- hostid: ${HOSTID}"
${ECHOCMD} "- hostid2: ${HOSTID2}"
if [ ${SAVEFILE} -eq 1 ]; then
FILE="${ROOTDIR}etc/lynis/hostids"
if [ -f ${FILE} ]; then
${ECHOCMD} "Error: hostids file already exists (${FILE})"
${ECHOCMD} "Remove the file first and rerun command"
ExitFatal
else
OUTPUT=$(touch ${FILE} 2> /dev/null)
if [ $? -eq 0 ]; then
${ECHOCMD} "Created hostids file (${FILE})"
echo "# generated using 'lynis generate hostids --save'" > ${FILE}
echo "hostid=${HOSTID}" >> ${FILE}
echo "hostid2=${HOSTID2}" >> ${FILE}
else
ExitFatal "Error: could not created hostids file (${FILE}). Issue with permissions?"
fi
fi
fi
ExitClean
;;
"cronjob")
${ECHOCMD} "Not implemented yet"
;;
"systemd-units")
${ECHOCMD} ""
${ECHOCMD} "${BG_BLUE}Step 1: create service unit (/etc/systemd/system/lynis.service)${NORMAL}"
${ECHOCMD} ""
${ECHOCMD} "#################################################################################"
${ECHOCMD} "#"
${ECHOCMD} "# Lynis service file for systemd"
${ECHOCMD} "#"
${ECHOCMD} "#################################################################################"
${ECHOCMD} "# Do not remove, so Lynis can provide a hint when a newer unit is available"
${ECHOCMD} "# Generator=lynis"
${ECHOCMD} "# Version=1"
${ECHOCMD} "#################################################################################"
${ECHOCMD} ""
${ECHOCMD} "[Unit]"
${ECHOCMD} "Description=Security audit and vulnerability scanner"
${ECHOCMD} "Documentation=https://cisofy.com/docs/"
${ECHOCMD} ""
${ECHOCMD} "[Service]"
${ECHOCMD} "Nice=19"
${ECHOCMD} "IOSchedulingClass=best-effort"
${ECHOCMD} "IOSchedulingPriority=7"
${ECHOCMD} "Type=simple"
MYBINARY=$(which lynis 2>/dev/null)
MOREOPTIONS=""
if [ -n "${LICENSE_KEY}" ]; then
MOREOPTIONS=" --upload"
fi
${ECHOCMD} "ExecStart=${MYBINARY:-/path/to/lynis} audit system --cronjob${MOREOPTIONS}"
${ECHOCMD} ""
${ECHOCMD} "[Install]"
${ECHOCMD} "WantedBy=multi-user.target"
${ECHOCMD} ""
${ECHOCMD} "#################################################################################"
${ECHOCMD} ""
${ECHOCMD} ""
${ECHOCMD} "${BG_BLUE}Step 2: create timer unit (/etc/systemd/system/lynis.timer)${NORMAL}"
${ECHOCMD} ""
${ECHOCMD} "#################################################################################"
${ECHOCMD} "#"
${ECHOCMD} "# Lynis timer file for systemd"
${ECHOCMD} "#"
${ECHOCMD} "#################################################################################"
${ECHOCMD} "# Do not remove, so Lynis can provide a hint when a newer unit is available"
${ECHOCMD} "# Generator=lynis"
${ECHOCMD} "# Version=1"
${ECHOCMD} "#################################################################################"
${ECHOCMD} ""
${ECHOCMD} "[Unit]"
${ECHOCMD} "Description=Daily timer for the Lynis security audit and vulnerability scanner"
${ECHOCMD} ""
${ECHOCMD} "[Timer]"
${ECHOCMD} "OnCalendar=daily"
${ECHOCMD} "RandomizedDelaySec=1800"
${ECHOCMD} "Persistent=false"
${ECHOCMD} ""
${ECHOCMD} "[Install]"
${ECHOCMD} "WantedBy=timers.target"
${ECHOCMD} ""
${ECHOCMD} "#################################################################################"
${ECHOCMD} ""
${ECHOCMD} ""
${ECHOCMD} "${BG_BLUE}Step 3 - Enable the timer${NORMAL}"
${ECHOCMD} ""
${ECHOCMD} "Tell systemd you made changes: systemctl daemon-reload"
${ECHOCMD} ""
${ECHOCMD} "Enable and start the timer (so no reboot is needed): systemctl enable --now lynis.timer"
${ECHOCMD} ""
${ECHOCMD} ""
${ECHOCMD} "${BG_BLUE}Optional - Customize${NORMAL}"
${ECHOCMD} ""
${ECHOCMD} "Want to override the timer? Run: systemctl edit lynis.timer"
${ECHOCMD} "Note: set the timer by first resetting it, then set the preferred value"
${ECHOCMD} ""
${ECHOCMD} "[Timer]"
${ECHOCMD} "OnCalendar="
${ECHOCMD} "OnCalendar=*-*-* 03:00:00"
${ECHOCMD} ""
;;
*) ${ECHOCMD} "Unknown argument '${RED}$1${NORMAL}' for lynis generate" ;;
esac
else
${ECHOCMD} "\n ${WHITE}Provide an additional argument${NORMAL}\n\n"
for ITEM in ${GENERATE_ARGS}; do
${ECHOCMD} " lynis generate ${BROWN}${ITEM}${NORMAL}"
done
${ECHOCMD} "\n"
${ECHOCMD} ""
${ECHOCMD} "Extended help about the generate command can be provided with: $0 show commands generate"
fi
ExitClean
# The End

View File

@ -28,7 +28,7 @@
#
######################################################################
COMMANDS="audit configure show update upload-only"
COMMANDS="audit configure generate show update upload-only"
HELPERS="audit configure show update"
OPTIONS="--auditor\n--cronjob (--cron)\n--debug\n--developer\n--help (-h)\n--license-key\n--log-file\n--manpage (--man)\n--no-colors\n--no-log\n--pentest\n--profile\n--plugin-dir\n--quick (-Q)\n--quiet (-q)\n--report-file\n--reverse-colors\n--skip-plugins\n--tests\n--tests-from-category\n--tests-from-group\n--upload\n--verbose\n--version (-V)\n--wait\n--warnings-only"
@ -94,6 +94,20 @@ AUDIT_HELP="
"
GENERATE_ARGS="( --save )"
GENERATE_HELP="
Generate random value for hostid and hostid2
${WHITE}lynis generate hostids${NORMAL}
Generate and save values
${WHITE}lynis generate hostids --save${NORMAL}
Generate systemd units to run Lynis on a schedule (e.g. daily)
${WHITE}lynis generate systemd-units${NORMAL}
"
UPDATE_ARGS="check info"
UPDATE_HELP="
${CYAN}update info${NORMAL}
@ -149,15 +163,15 @@ if [ $# -gt 0 ]; then
if [ ! -z "${CHANGELOG}" ]; then LogText "Result: found changelog file: ${CHANGELOG}"; break; fi
done
if [ ! -z "${CHANGELOG}" ]; then
SEARCH=$(egrep "^${PROGRAM_NAME} ${SEARCH_VERSION}" ${CHANGELOG})
SEARCH=$(sed 's/^## //' ${CHANGELOG} | grep -E "^${PROGRAM_NAME} ${SEARCH_VERSION}")
if [ $? -eq 0 ]; then
while read -r LINE; do
if [ ${STARTED} -eq 0 ]; then
SEARCH=$(echo ${LINE} | egrep "^${PROGRAM_NAME} ${SEARCH_VERSION}")
SEARCH=$(echo ${LINE} | sed 's/^## //' | grep -E "^${PROGRAM_NAME} ${SEARCH_VERSION}")
if [ $? -eq 0 ]; then STARTED=1; ${ECHOCMD} "${BOLD}${LINE}${NORMAL}"; fi
else
# Stop if we find the next Lynis version
SEARCH=$(echo ${LINE} | egrep "^${PROGRAM_NAME} [0-9]\.[0-9]\.[0-9]")
SEARCH=$(echo ${LINE} | sed 's/^## //' | grep -E "^${PROGRAM_NAME} [0-9]\.[0-9]\.[0-9]")
if [ $? -eq 0 ]; then
break
else
@ -172,7 +186,7 @@ if [ $# -gt 0 ]; then
${ECHOCMD} "$0 lynis show changelog [version]"
${ECHOCMD} ""
${ECHOCMD} "${HEADER}${PROGRAM_NAME} versions:${NORMAL}"
SEARCH=$(egrep "^Lynis [0-9]\.[0-9]\.[0-9] " ${CHANGELOG} | awk '{print $2}' | sort -n)
SEARCH=$(sed 's/^## //' ${CHANGELOG} | grep -E "^Lynis [0-9]\.[0-9]\.[0-9] " | awk '{print $2}' | sort -n)
${ECHOCMD} ${SEARCH}
ExitFatal
fi
@ -274,6 +288,7 @@ if [ $# -gt 0 ]; then
shift
case $1 in
"audit") ${ECHOCMD} "${AUDIT_HELP}" ;;
"generate") ${ECHOCMD} "${GENERATE_HELP}" ;;
"show") ${ECHOCMD} "${SHOW_HELP}" ;;
"update") ${ECHOCMD} "${UPDATE_HELP}" ;;
"upload-only") ${ECHOCMD} "${UPLOAD_ONLY_HELP}" ;;

View File

@ -477,7 +477,7 @@
ECHONB=""
case ${OS} in
"AIX") ECHOCMD="echo" ;;
"AIX") ECHOCMD="echo"; ECHONB="printf" ;;
"DragonFly"|"FreeBSD"|"NetBSD") ECHOCMD="echo -e"; ECHONB="echo -n" ;;
"macOS" | "Mac OS X") ECHOCMD="echo"; ECHONB="/bin/echo -n" ;;
"Solaris") ECHOCMD="echo" ; test -f /usr/ucb/echo && ECHONB="/usr/ucb/echo -n" ;;

View File

@ -22,8 +22,21 @@
#
#################################################################################
#
# Check number of parameters submitted (at least one is needed)
PARAMCOUNT=$#
# Input validation on provided parameters and their arguments
COUNT=0
for I in "$@"; do
COUNT=$((COUNT + 1))
if ! SafeInput "${I}"; then
echo "Execution of ${PROGRAM_NAME} stopped as we found unexpected input or invalid characters in argument ${COUNT}"
echo "Do you believe this is in error? Let us know: ${PROGRAM_AUTHOR_CONTACT}"
ExitFatal "Program execution stopped due to security measure"
fi
done
# Parse arguments
while [ $# -ge 1 ]; do
case $1 in
# Helpers first
@ -36,12 +49,13 @@
if [ $# -gt 1 ]; then
case $2 in
"dockerfile")
if [ "$3" = "" ]; then
if [ $# = 2 ]; then
echo "${RED}Error: ${WHITE}Missing file name or URL${NORMAL}"
echo "Example: $0 audit dockerfile /root/Dockerfile"
echo "Example: $0 audit dockerfile /path/to/Dockerfile"
ExitFatal
else
shift; shift
CHECK_BINARIES=1
HELPER_PARAMS="$1"
HELPER="audit_dockerfile"
break
@ -111,6 +125,24 @@
break
;;
# Generate data
generate)
CHECK_BINARIES=0
HELPER="generate"
LOGTEXT=0
QUIET=1
RUN_HELPERS=1
RUN_TESTS=0
RUN_UPDATE_CHECK=0
SKIP_GETHOSTID=1
SKIP_PLUGINS=1
SKIP_VM_DETECTION=1
SHOW_PROGRAM_DETAILS=0
SHOW_TOOL_TIPS=0
shift; HELPER_PARAMS="$@"
break
;;
# Show Lynis details
show)
CHECK_BINARIES=0
@ -201,7 +233,7 @@
# Cronjob support
--cron-job | --cronjob | --cron)
CRONJOB=1
CHECK=1; QUICKMODE=1; COLORS=0; NEVERBREAK=1 # Use some defaults (-c, -Q, no colors)
CHECK=1; COLORS=0; NEVERBREAK=1 # Use some defaults ('audit system', -Q, no colors)
RemoveColors
;;
@ -313,7 +345,6 @@
# Quiet mode
--quiet | -q | --silent)
QUIET=1
QUICKMODE=1 # Run non-interactive
;;
# Non-interactive mode
@ -412,7 +443,6 @@
# Warnings
--warnings-only | --show-warnings-only)
SHOW_WARNINGS_ONLY=1
QUICKMODE=1
QUIET=1
;;
@ -433,5 +463,15 @@
done
# Ensure non-interactive mode when running quietly or as cronjob
if [ ${CRONJOB} -eq 1 -o ${QUIET} -eq 1 ]; then
if [ ${QUICKMODE} -eq 0 ]; then
if [ ${QUIET} -eq 0 ]; then
echo "Switched back to quick mode (cron/non-interactive/quiet)"
fi
QUICKMODE=1
fi
fi
#================================================================================
# Lynis - Security Auditing and System Hardening for Linux and UNIX - https://cisofy.com

View File

@ -32,9 +32,38 @@
for PROFILE in ${PROFILES}; do
LogText "Reading profile/configuration ${PROFILE}"
FIND=$(egrep "^config:|^[a-z-].*=" ${PROFILE} | sed 's/ /!space!/g')
for CONFIGOPTION in ${FIND}; do
if ContainsString "config:" "${CONFIGOPTION}"; then
# Show deprecation message for old config entries
FOUND=0
#DATA=$(egrep "^config:" ${PROFILE} | od --address-radix=none -t a | sed 's/ /!space!/g')
#if ! IsEmpty "${DATA}"; then FOUND=1; fi
# Items such as 'apache:'
DATA=$(egrep "^[a-z-]{1,}:" ${PROFILE} | od --address-radix=none -t a | sed 's/ /!space!/g')
if ! IsEmpty "${DATA}"; then FOUND=1; fi
if [ ${FOUND} -eq 1 ]; then
DisplayWarning "Your profile contains old-style configuration entries. See log file for more details and how to convert these entries"
LogText "Your profile has one or more configuration items that are in an old format (lines starting with key:value). They need to be converted into the new format (key=value)."
LogText "Tip: Use egrep to see the relevant matches (egrep \"^[a-z-]{1,}:\" custom.prf)"
sleep 30
fi
# Security check for unexpected and possibly harmful escape characters
DATA=$(grep -v '^$\|^ \|^#\|^config:' ${PROFILE} | tr -d '[:alnum:]/\[\]\(\)\-_\|,\.:;= \n\r' | od --address-radix=none -t a | sed 's/ /!space!/g')
if ! IsEmpty "${DATA}"; then
DisplayWarning "Your profile '${PROFILE}' contains unexpected characters. See the log file for more information."
LogText "Found unexpected or possibly harmful characters in the profile. See output below."
for I in "${DATA}"; do
I=$(echo ${I} | sed 's/!space!/ /g')
LogText "Output: ${I}"
done
sleep 30
fi
# Now parse the profile and filter out unwanted characters
DATA=$(egrep "^config:|^[a-z-].*=" ${PROFILE} | tr -dc '[:alnum:]/\[\]\(\)\-_\|,\.:;= \n\r' | sed 's/ /!space!/g')
for CONFIGOPTION in ${DATA}; do
if ContainsString "^config:" "${CONFIGOPTION}"; then
# Old style configuration
OPTION=$(echo ${CONFIGOPTION} | cut -d ':' -f2)
VALUE=$(echo ${CONFIGOPTION} | cut -d ':' -f3 | sed 's/!space!/ /g')
@ -90,7 +119,7 @@
;;
# Ignore configuration data
config-data)
config-data | permdir | permfile)
Debug "Ignoring configuration option, as it will be used by a specific test"
;;
@ -239,6 +268,11 @@
LogText "Plugin '${VALUE}' enabled according profile (${PROFILE})"
;;
disable-plugin)
LogText "Plugin '${VALUE}' disabled according profile (${PROFILE})"
DISABLED_PLUGINS="${DISABLED_PLUGINS} ${VALUE}"
;;
# Plugin directory
plugindir | plugin-dir)
if IsEmpty "${PLUGINDIR}"; then
@ -256,9 +290,9 @@
# Quick (no waiting for keypresses)
quick)
# Quick mode (SKIP_PLUGINS) might already be set outside profile, so store in different variable
SETTING_QUICK_MODE=0 # default is no
FIND=$(echo "${VALUE}" | egrep "^(1|true|yes)$") && QUICKMODE=1
# Quick mode might already be set outside profile, so store in different variable
SETTING_QUICK_MODE=1 # default is yes
FIND=$(echo "${VALUE}" | egrep "^(0|false|no)$") && QUICKMODE=0
if [ ! -z "${FIND}" ]; then SETTING_QUICK_MODE=1; fi
Debug "Quickmode set to ${SETTING_QUICK_MODE}"
AddSetting "quick" "${SETTING_QUICK_MODE}" "Quick mode (non-interactive)"
@ -328,6 +362,13 @@
AddSetting "ssl-certificate-paths" "${SSL_CERTIFICATE_PATHS}" "Paths for SSL certificates"
;;
ssl-certificate-paths-to-ignore)
# Retrieve paths to ignore when searching for certificates. Strip special characters, replace possible spaces
SSL_CERTIFICATE_PATHS_TO_IGNORE=$(echo ${VALUE} | tr -d '[:cntrl:]' | sed 's/ /__space__/g' | tr ':' ' ')
Debug "SSL paths to ignore: ${SSL_CERTIFICATE_PATHS_TO_IGNORE}"
AddSetting "ssl-certificate-paths-to-ignore" "${SSL_CERTIFICATE_PATHS_TO_IGNORE}" "Paths that should be ignored for SSL certificates"
;;
# Set strict mode for development and quality purposes
strict)
FIND=$(echo "${VALUE}" | egrep "^(1|true|yes)") && SET_STRICT=1
@ -441,10 +482,14 @@
# Catch all bad options and bail out
*)
LogText "Unknown option ${OPTION} (with value: ${VALUE})"
${ECHOCMD} ""
${ECHOCMD} "${RED}Error${NORMAL}: found one or more errors in profile ${PROFILE}"
${ECHOCMD} "${WHITE}Details${NORMAL}: Unknown option '${YELLOW}${OPTION}${NORMAL}' found (with value: ${VALUE})"
${ECHOCMD} ""
${ECHOCMD:-echo} ""
${ECHOCMD:-echo} "${RED}Error${NORMAL}: found one or more errors in profile ${PROFILE}"
${ECHOCMD:-echo} ""
${ECHOCMD:-echo} ""
${ECHOCMD:-echo} "Full line: ${CONFIGOPTION}"
${ECHOCMD:-echo} "${WHITE}Details${NORMAL}: Unknown option '${YELLOW}${OPTION}${NORMAL}' found (with value: ${VALUE})"
${ECHOCMD:-echo} ""
ExitFatal
;;

View File

@ -22,55 +22,79 @@
#
#################################################################################
#
# Add data fields to report file
Report "dhcp_client_running=${DHCP_CLIENT_RUNNING}"
Report "arpwatch_running=${ARPWATCH_RUNNING}"
# Report firewall installed for now, if we found one active. Next step would be determining binaries first and apply additional checks.
Report "firewall_active=${FIREWALL_ACTIVE}"
Report "firewall_empty_ruleset=${FIREWALL_EMPTY_RULESET}"
Report "firewall_installed=${FIREWALL_ACTIVE}"
if [ ! -z "${INSTALLED_PACKAGES}" ]; then Report "installed_packages_array=${INSTALLED_PACKAGES}"; fi
Report "package_audit_tool=${PACKAGE_AUDIT_TOOL}"
Report "package_audit_tool_found=${PACKAGE_AUDIT_TOOL_FOUND}"
Report "vulnerable_packages_found=${VULNERABLE_PACKAGES_FOUND}"
# Hardening Index
# Define approximately how strong a machine has been hardened
# If no hardening has been found, set value to 1
if [ ${HPPOINTS} -eq 0 ]; then HPPOINTS=1; HPTOTAL=100; fi
HPINDEX=$((HPPOINTS * 100 / HPTOTAL))
HPAOBLOCKS=$((HPPOINTS * 20 / HPTOTAL))
# Set color related to rating
if [ ${HPINDEX} -lt 50 ]; then
HPCOLOR="${RED}"
HIDESCRIPTION="System has not or a low amount been hardened"
elif [ ${HPINDEX} -gt 49 -a ${HPINDEX} -lt 80 ]; then
HPCOLOR="${YELLOW}"
HIDESCRIPTION="System has been hardened, but could use additional hardening"
elif [ ${HPINDEX} -gt 79 -a ${HPINDEX} -lt 90 ]; then
HPCOLOR="${GREEN}"
HIDESCRIPTION="System seem to be decent hardened"
elif [ ${HPINDEX} -gt 89 ]; then
HPCOLOR="${GREEN}"
HIDESCRIPTION="System seem to be well hardened"
fi
# Goal:
# Provide a visual way to show how much the system is hardened
#
# Important:
# The index gives a simplified version of the measures taken on the system.
# It should be used to get a first impression about the state of the system or to compare similar systems.
# Getting the maximum score (100 or full bar) does not indicate that the system is fully secured.
case ${HPAOBLOCKS} in
0) HPBLOCKS="#"; HPEMPTY=" " ;;
1) HPBLOCKS="#"; HPEMPTY=" " ;;
2) HPBLOCKS="##"; HPEMPTY=" " ;;
3) HPBLOCKS="###"; HPEMPTY=" " ;;
4) HPBLOCKS="####"; HPEMPTY=" " ;;
5) HPBLOCKS="#####"; HPEMPTY=" " ;;
6) HPBLOCKS="######"; HPEMPTY=" " ;;
7) HPBLOCKS="#######"; HPEMPTY=" " ;;
8) HPBLOCKS="########"; HPEMPTY=" " ;;
9) HPBLOCKS="#########"; HPEMPTY=" " ;;
10) HPBLOCKS="##########"; HPEMPTY=" " ;;
11) HPBLOCKS="###########"; HPEMPTY=" " ;;
12) HPBLOCKS="############"; HPEMPTY=" " ;;
13) HPBLOCKS="#############"; HPEMPTY=" " ;;
14) HPBLOCKS="##############"; HPEMPTY=" " ;;
15) HPBLOCKS="###############"; HPEMPTY=" " ;;
16) HPBLOCKS="################"; HPEMPTY=" " ;;
17) HPBLOCKS="#################"; HPEMPTY=" " ;;
18) HPBLOCKS="##################"; HPEMPTY=" " ;;
19) HPBLOCKS="###################"; HPEMPTY=" " ;;
20) HPBLOCKS="####################"; HPEMPTY="" ;;
esac
# If no hardening has been found, set value to 1
if [ ${HPPOINTS} -eq 0 ]; then HPPOINTS=1; HPTOTAL=100; fi
HPINDEX=$((HPPOINTS * 100 / HPTOTAL))
HPAOBLOCKS=$((HPPOINTS * 20 / HPTOTAL))
# Set color related to rating
if [ ${HPINDEX} -lt 50 ]; then
HPCOLOR="${RED}"
HIDESCRIPTION="System has not or a low amount been hardened"
elif [ ${HPINDEX} -gt 49 -a ${HPINDEX} -lt 80 ]; then
HPCOLOR="${YELLOW}"
HIDESCRIPTION="System has been hardened, but could use additional hardening"
elif [ ${HPINDEX} -gt 79 -a ${HPINDEX} -lt 90 ]; then
HPCOLOR="${GREEN}"
HIDESCRIPTION="System seem to be decent hardened"
elif [ ${HPINDEX} -gt 89 ]; then
HPCOLOR="${GREEN}"
HIDESCRIPTION="System seem to be well hardened"
fi
HPGRAPH="[${HPCOLOR}${HPBLOCKS}${NORMAL}${HPEMPTY}]"
LogText "Hardening index : [${HPINDEX}] [${HPBLOCKS}${HPEMPTY}]"
LogText "Hardening strength: ${HIDESCRIPTION}"
case ${HPAOBLOCKS} in
0) HPBLOCKS="#"; HPEMPTY=" " ;;
1) HPBLOCKS="#"; HPEMPTY=" " ;;
2) HPBLOCKS="##"; HPEMPTY=" " ;;
3) HPBLOCKS="###"; HPEMPTY=" " ;;
4) HPBLOCKS="####"; HPEMPTY=" " ;;
5) HPBLOCKS="#####"; HPEMPTY=" " ;;
6) HPBLOCKS="######"; HPEMPTY=" " ;;
7) HPBLOCKS="#######"; HPEMPTY=" " ;;
8) HPBLOCKS="########"; HPEMPTY=" " ;;
9) HPBLOCKS="#########"; HPEMPTY=" " ;;
10) HPBLOCKS="##########"; HPEMPTY=" " ;;
11) HPBLOCKS="###########"; HPEMPTY=" " ;;
12) HPBLOCKS="############"; HPEMPTY=" " ;;
13) HPBLOCKS="#############"; HPEMPTY=" " ;;
14) HPBLOCKS="##############"; HPEMPTY=" " ;;
15) HPBLOCKS="###############"; HPEMPTY=" " ;;
16) HPBLOCKS="################"; HPEMPTY=" " ;;
17) HPBLOCKS="#################"; HPEMPTY=" " ;;
18) HPBLOCKS="##################"; HPEMPTY=" " ;;
19) HPBLOCKS="###################"; HPEMPTY=" " ;;
20) HPBLOCKS="####################"; HPEMPTY="" ;;
esac
HPGRAPH="[${HPCOLOR}${HPBLOCKS}${NORMAL}${HPEMPTY}]"
LogText "Hardening index : [${HPINDEX}] [${HPBLOCKS}${HPEMPTY}]"
LogText "Hardening strength: ${HIDESCRIPTION}"
# Only show overview if not running in quiet mode

View File

@ -40,7 +40,12 @@
if [ ${SKIPTEST} -eq 0 ]; then
# Search accounts with UID 0
LogText "Test: Searching accounts with UID 0"
FIND=$(${GREPBINARY} ':0:' ${ROOTDIR}etc/passwd | ${EGREPBINARY} -v '^#|^root:|^(\+:\*)?:0:0:::' | ${CUTBINARY} -d ":" -f1,3 | ${GREPBINARY} ':0')
# Check if device is a QNAP, as the root user is called admin, and not root
if [ ${QNAP_DEVICE} -eq 1 ]; then
FIND=$(${GREPBINARY} ':0:' ${ROOTDIR}etc/passwd | ${EGREPBINARY} -v '^#|^admin:|^(\+:\*)?:0:0:::' | ${CUTBINARY} -d ":" -f1,3 | ${GREPBINARY} ':0')
else
FIND=$(${GREPBINARY} ':0:' ${ROOTDIR}etc/passwd | ${EGREPBINARY} -v '^#|^root:|^(\+:\*)?:0:0:::' | ${CUTBINARY} -d ":" -f1,3 | ${GREPBINARY} ':0')
fi
if [ ! -z "${FIND}" ]; then
Display --indent 2 --text "- Administrator accounts" --result "${STATUS_WARNING}" --color RED
LogText "Result: Found more than one administrator accounts"
@ -669,8 +674,8 @@
if [ -d ${DIR} -a ! -L ${DIR} ]; then
LogText "Result: directory ${DIR} exists"
# Search in the specified directory
if [ "${OS}" = "Solaris" ]; then
# Solaris does not support -maxdepth
if [ "${OS}" = "AIX" -o "${OS}" = "Solaris" ]; then
# AIX/Solaris does not support -maxdepth
FIND=$(find ${DIR} -type f -name "pam_*.so" -print | sort)
else
FIND=$(find ${DIR} -maxdepth 1 -type f -name "pam_*.so" -print | sort)
@ -698,25 +703,32 @@
#
# Test : AUTH-9278
# Description : Search LDAP support in PAM files
Register --test-no AUTH-9278 --weight L --network NO --category security --description "Checking LDAP pam status"
Register --test-no AUTH-9278 --weight L --network NO --category security --description "Determine LDAP support in PAM files"
if [ ${SKIPTEST} -eq 0 ]; then
LogText "Test: checking presence /etc/pam.d/common-auth"
if [ -f /etc/pam.d/common-auth ]; then
LogText "Result: file /etc/pam.d/common-auth exists"
LogText "Test: checking presence LDAP module"
FIND=$(${GREPBINARY} "^auth.*ldap" /etc/pam.d/common-auth)
if [ ! "${FIND}" = "" ]; then
LogText "Result: LDAP module present"
LogText "Output: ${FIND}"
Display --indent 2 --text "- LDAP module in PAM" --result "${STATUS_FOUND}" --color GREEN
LDAP_AUTH_ENABLED=1
LDAP_PAM_ENABLED=1
AUTH_FILES="${ROOTDIR}etc/pam.d/common-auth ${ROOTDIR}etc/pam.d/system-auth"
for FILE in ${AUTH_FILES}; do
LogText "Test: checking presence ${FILE}"
if [ -f ${FILE} ]; then
LogText "Result: file ${FILE} exists"
LogText "Test: checking presence LDAP module"
FIND=$(${GREPBINARY} "^auth.*ldap" ${FILE})
if [ ! -z "${FIND}" ]; then
LogText "Result: LDAP module present"
LogText "Output: ${FIND}"
LDAP_AUTH_ENABLED=1
LDAP_PAM_ENABLED=1
else
LogText "Result: LDAP module not found"
fi
else
LogText "Result: LDAP module not found"
Display --indent 2 --text "- LDAP module in PAM" --result "${STATUS_NOT_FOUND}" --color WHITE
LogText "Result: file ${FILE} not found, skipping test"
fi
done
if [ ${LDAP_PAM_ENABLED} -eq 1 ]; then
Display --indent 2 --text "- LDAP module in PAM" --result "${STATUS_FOUND}" --color GREEN
else
LogText "Result: file /etc/pam.d/common-auth not found, skipping test"
Display --indent 2 --text "- LDAP module in PAM" --result "${STATUS_NOT_FOUND}" --color WHITE
fi
fi
#

View File

@ -96,7 +96,11 @@
;;
"init" | "initsplash")
SERVICE_MANAGER="SysV Init"
if [ -d ${ROOTDIR}etc/rc.d ]; then
SERVICE_MANAGER="bsdrc.d"
else
SERVICE_MANAGER="SysV Init"
fi
;;
systemd)
SERVICE_MANAGER="systemd"

View File

@ -34,55 +34,78 @@
COUNT_EXPIRED=0
COUNT_TOTAL=0
FOUNDPROBLEM=0
sSSL_PATHS=$(echo ${SSL_CERTIFICATE_PATHS} | ${SEDBINARY} 's/:/ /g')
sSSL_PATHS=$(echo ${sSSL_PATHS} | ${SEDBINARY} 's/^ //' | ${TRBINARY} " " "\n" | ${SORTBINARY} | uniq | ${TRBINARY} "\n" " ")
SKIP=0
sSSL_PATHS=$(echo ${SSL_CERTIFICATE_PATHS} | ${SEDBINARY} 's/:space:/__space__/g' | ${SEDBINARY} 's/:/ /g')
sSSL_PATHS=$(echo ${sSSL_PATHS} | ${SEDBINARY} 's/^ //' | ${SORTBINARY} | ${UNIQBINARY})
LogText "Paths to scan: ${sSSL_PATHS}"
IGNORE_PATHS_PRINT=$(echo ${SSL_CERTIFICATE_PATHS_TO_IGNORE} | ${SEDBINARY} 's/:/, /g' | ${SEDBINARY} 's/__space__/ /g' | ${SEDBINARY} 's/^ //' | ${SORTBINARY} | ${UNIQBINARY})
LogText "Paths to ignore: ${IGNORE_PATHS_PRINT}"
for DIR in ${sSSL_PATHS}; do
COUNT_DIR=0
if [ -d ${DIR} ]; then
FileIsReadable ${DIR}
if [ ${CANREAD} -eq 1 ]; then
LASTSUBDIR=""
LogText "Result: found directory ${DIR}"
# Search for certificate files
FILES=$(${FINDBINARY} ${DIR} -type f 2> /dev/null | ${EGREPBINARY} ".crt$|.pem$|^cert" | ${SORTBINARY} | ${SEDBINARY} 's/ /:space:/g')
FILES=$(${FINDBINARY} ${DIR} -type f 2> /dev/null | ${EGREPBINARY} ".crt$|.pem$|^cert" | ${SORTBINARY} | ${SEDBINARY} 's/ /__space__/g')
for FILE in ${FILES}; do
FILE=$(echo ${FILE} |${SEDBINARY} 's/:space:/ /g')
COUNT_DIR=$((COUNT_DIR + 1))
FileIsReadable "${FILE}"
if [ ${CANREAD} -eq 1 ]; then
# Only check the files that are not installed by a package
if ! FileInstalledByPackage "${FILE}"; then
LogText "Test: test if file is a certificate"
OUTPUT=$(${GREPBINARY} -q 'BEGIN CERT' "${FILE}")
if [ $? -eq 0 ]; then
LogText "Result: file is a certificate"
LogText "Test: checking certificate details"
FIND=$(${OPENSSLBINARY} x509 -noout -in "${FILE}" -enddate 2> /dev/null | ${GREPBINARY} "^notAfter")
FILE=$(echo ${FILE} | ${SEDBINARY} 's/__space__/ /g')
# See if we need to skip this path
SUBDIR=$(echo ${FILE} | ${AWKBINARY} -F/ 'sub(FS $NF,x)' | ${SEDBINARY} 's/__space__/ /g')
# If we discover a new directory, do evaluation
#Debug "File : ${FILE}"
#Debug "Lastdir: ${LASTSUBDIR}"
#Debug "Curdir : ${SUBDIR}"
if [ ! "${SUBDIR}" = "${LASTSUBDIR}" ]; then
SKIP=0
# Now check if this path is on the to-be-ignored list
for D in ${SSL_CERTIFICATE_PATHS_TO_IGNORE}; do
if Equals "${D}" "${SUBDIR}"; then
SKIP=1
LogText "Result: skipping directory (${SUBDIR}) as it is on ignore list"
fi
done
fi
if [ ${SKIP} -eq 0 ]; then
#Debug "Testing ${FILE} in path: $SUBDIR"
COUNT_DIR=$((COUNT_DIR + 1))
FileIsReadable "${FILE}"
if [ ${CANREAD} -eq 1 ]; then
# Only check the files that are not installed by a package
if ! FileInstalledByPackage "${FILE}"; then
OUTPUT=$(${GREPBINARY} -q 'BEGIN CERT' "${FILE}")
if [ $? -eq 0 ]; then
# Check certificate where 'end date' has been expired
FIND=$(${OPENSSLBINARY} x509 -noout -checkend 0 -in "${FILE}" -enddate 2> /dev/null)
EXIT_CODE=$?
CERT_CN=$(${OPENSSLBINARY} x509 -noout -subject -in "${FILE}" 2> /dev/null | ${SEDBINARY} -e 's/^subject.*CN=\([a-zA-Z0-9\.\-\*]*\).*$/\1/')
CERT_NOTAFTER=$(${OPENSSLBINARY} x509 -noout -enddate -in "${FILE}" 2> /dev/null | ${AWKBINARY} -F= '{if ($1=="notAfter") { print $2 }}')
Report "certificate[]=${FILE}|${EXIT_CODE}|cn:${CERT_CN};notafter:${CERT_NOTAFTER};|"
if [ ${EXIT_CODE} -eq 0 ]; then
LogText "Result: certificate ${FILE} seems to be correct and still valid"
LogText "Result: file is a certificate file"
FIND=$(${OPENSSLBINARY} x509 -noout -in "${FILE}" -enddate 2> /dev/null | ${GREPBINARY} "^notAfter")
if [ $? -eq 0 ]; then
# Check certificate where 'end date' has been expired
FIND=$(${OPENSSLBINARY} x509 -noout -checkend 0 -in "${FILE}" -enddate 2> /dev/null)
EXIT_CODE=$?
CERT_CN=$(${OPENSSLBINARY} x509 -noout -subject -in "${FILE}" 2> /dev/null | ${SEDBINARY} -e 's/^subject.*CN=\([a-zA-Z0-9\.\-\*]*\).*$/\1/')
CERT_NOTAFTER=$(${OPENSSLBINARY} x509 -noout -enddate -in "${FILE}" 2> /dev/null | ${AWKBINARY} -F= '{if ($1=="notAfter") { print $2 }}')
Report "certificate[]=${FILE}|${EXIT_CODE}|cn:${CERT_CN};notafter:${CERT_NOTAFTER};|"
if [ ${EXIT_CODE} -eq 0 ]; then
LogText "Result: certificate ${FILE} seems to be correct and still valid"
else
FOUNDPROBLEM=1
COUNT_EXPIRED=$((COUNT_EXPIRED + 1))
LogText "Result: certificate ${FILE} has been expired"
fi
else
FOUNDPROBLEM=1
COUNT_EXPIRED=$((COUNT_EXPIRED + 1))
LogText "Result: certificate ${FILE} has been expired"
LogText "Result: skipping tests for this file (${FILE}) as it is most likely not a certificate (is it a key file?)"
fi
else
LogText "Result: skipping tests for this file (${FILE}) as it is most likely not a certificate (a key file?)"
LogText "Result: skipping test for this file (${FILE}) as we could not find 'BEGIN CERT'"
fi
else
LogText "Result: skipping test for this file (${FILE}) as we could not find 'BEGIN CERT'"
fi
else
LogText "Result: can not read file ${FILE} (no permission)"
fi
else
LogText "Result: can not read file ${FILE} (no permission)"
fi
LASTSUBDIR="${SUBDIR}"
done
COUNT_TOTAL=$((COUNT_TOTAL + COUNT_DIR))
LogText "Result: found ${COUNT_DIR} certificates in ${DIR}"
@ -105,6 +128,30 @@
fi
#
#################################################################################
#
# Test : CRYP-7930
# Description : Determine if system uses disk or file encryption
Register --test-no CRYP-7930 --weight L --network NO --category security --description "Determine if system uses disk or file encryption"
if [ ${SKIPTEST} -eq 0 ]; then
FILE="${ROOTDIR}etc/crypttab"
if [ -f ${FILE} ]; then
LogText "Result: crypttab file (${FILE}) exists"
DATA=$(${GREPBINARY} "^[a-z]" ${FILE} | ${TRBINARY} -cd '[:alnum:]_\-=,\n\t ' | ${SEDBINARY} 's/[[:blank:]]/__space__/g')
for LINE in ${DATA}; do
LINE=$(echo ${LINE} | ${SEDBINARY} 's/__space__/ /g')
if ContainsString "luks," "${LINE}"; then
PARTITION=$(echo ${LINE} | ${AWKBINARY} '{print $1}' | ${AWKBINARY} -F_ '{print $1}')
LogText "Result: Found LUKS encryption on partition ${PARTITION}"
Report "encryption[]=luks,partition,${PARTITION}"
fi
done
unset DATA LINE PARTITION
else
LogText "Result: crypttab file (${FILE}) does not exist"
fi
fi
#
#################################################################################
#
WaitForKeyPress

View File

@ -34,10 +34,10 @@
LogText "Test: Checking file permissions"
for PROFILE in ${PROFILES}; do
LogText "Using profile ${PROFILE} for baseline."
FIND=$(${EGREPBINARY} '^permfile:|^permdir:' ${PROFILE} | ${CUTBINARY} -d: -f2)
FIND=$(${EGREPBINARY} '^permfile=|^permdir=' ${PROFILE} | ${CUTBINARY} -d= -f2)
for I in ${FIND}; do
LogText "Checking ${I}"
CheckFilePermissions ${I}
CheckFilePermissions "${I}"
LogText " Expected permissions: ${PROFILEVALUE}"
LogText " Actual permissions: ${FILEVALUE}"
LogText " Result: $PERMS"

View File

@ -48,7 +48,11 @@
Display --indent 4 --text "- Checking ${I} mount point" --result SYMLINK --color WHITE
elif [ -d ${I} ]; then
LogText "Result: directory ${I} exists"
FIND=$(${MOUNTBINARY} | ${AWKBINARY} -v MP=${I} '{ if ($3==MP) { print $3 }}')
case "${OS}" in
"AIX") FIND=$(${MOUNTBINARY} | ${AWKBINARY} -v MP=${I} '{ if ($2==MP) { print $2 }}') ;;
*) FIND=$(${MOUNTBINARY} | ${AWKBINARY} -v MP=${I} '{ if ($3==MP) { print $3 }}') ;;
esac
if IsEmpty "${FIND}"; then
LogText "Result: ${I} not found in mount list. Directory most likely stored on / file system"
Display --indent 4 --text "- Checking ${I} mount point" --result "${STATUS_SUGGESTION}" --color YELLOW
@ -158,7 +162,27 @@
done
else
LogText "Result: no EXT file systems found"
Report "file_systems_ext[]=none"
fi
fi
#
#################################################################################
#
# Test : FILE-6324
# Description : Checking Linux XFS file systems
Register --test-no FILE-6324 --os Linux --weight L --network NO --category security --description "Checking XFS file systems"
if [ ${SKIPTEST} -eq 0 ]; then
LogText "Test: Checking for Linux XFS file systems"
FIND=$(${MOUNTBINARY} -t xfs | ${AWKBINARY} '{ print $3","$5 }')
if [ ! -z "${FIND}" ]; then
LogText "Result: found one or more XFS file systems"
for I in ${FIND}; do
FILESYSTEM=$(echo ${I} | ${CUTBINARY} -d ',' -f1)
FILETYPE=$(echo ${I} | ${CUTBINARY} -d ',' -f2)
LogText "File system: ${FILESYSTEM} (type: ${FILETYPE})"
Report "file_systems_xfs[]=${FILESYSTEM}|${FILETYPE}|"
done
else
LogText "Result: no XFS file systems found"
fi
fi
#
@ -540,13 +564,13 @@
# ---------------------------------------------------------
FILESYSTEMS_TO_CHECK="/boot:nodev,noexec,nosuid /dev/shm:nosuid,nodev,noexec /home:nodev,nosuid /tmp:nodev,noexec,nosuid /var:nosuid /var/log:nodev,noexec,nosuid /var/log/audit:nodev,noexec,nosuid /var/tmp:nodev,noexec,nosuid"
Register --test-no FILE-6374 --os Linux --weight L --network NO --category security --description "Checking /boot mount options"
Register --test-no FILE-6374 --os Linux --weight L --network NO --category security --description "Checking partitions mount options"
if [ ${SKIPTEST} -eq 0 ]; then
if [ -f /etc/fstab ]; then
for I in ${FILESYSTEMS_TO_CHECK}; do
FILESYSTEM=$(echo ${I} | ${CUTBINARY} -d: -f1)
EXPECTED_FLAGS=$(echo ${I} | ${CUTBINARY} -d: -f2 | ${SEDBINARY} 's/,/ /g')
FS_FSTAB=$(${AWKBINARY} -v fs=${FILESYSTEM} '{ if ($2==fs) { print $3 } }' /etc/fstab)
FS_FSTAB=$(${AWKBINARY} -v fs=${FILESYSTEM} '{ if ($2==fs) { print $3 } }' ${ROOTDIR}etc/fstab)
if [ "${FS_FSTAB}" = "glusterfs" ]; then
EXPECTED_FLAGS=$(echo ${EXPECTED_FLAGS} | ${SEDBINARY} 's/\<\(nodev\|nosuid\)\> *//g')
if [ -z "${EXPECTED_FLAGS}" ]; then
@ -554,7 +578,7 @@
fi
fi
if [ ! -z "${FS_FSTAB}" ]; then
FOUND_FLAGS=$(${AWKBINARY} -v fs=${FILESYSTEM} '{ if ($2==fs) { print $4 } }' /etc/fstab | ${SEDBINARY} 's/,/ /g' | ${TRBINARY} '\n' ' ')
FOUND_FLAGS=$(${AWKBINARY} -v fs=${FILESYSTEM} '{ if ($2==fs) { print $4 } }' ${ROOTDIR}etc/fstab | ${SEDBINARY} 's/,/ /g' | ${TRBINARY} '\n' ' ')
LogText "File system: ${FILESYSTEM}"
LogText "Expected flags: ${EXPECTED_FLAGS}"
LogText "Found flags: ${FOUND_FLAGS}"
@ -562,7 +586,7 @@
FULLY_HARDENED=1
for FLAG in ${EXPECTED_FLAGS}; do
FLAG_AVAILABLE=$(echo ${FOUND_FLAGS} | ${GREPBINARY} ${FLAG})
if [ "${FLAG_AVAILABLE}" = "" ]; then
if [ -z "${FLAG_AVAILABLE}" ]; then
LogText "Result: Could not find mount option ${FLAG} on file system ${FILESYSTEM}"
FULLY_HARDENED=0
else

View File

@ -596,11 +596,6 @@
#################################################################################
#
# Report firewall installed for now, if we found one active. Next step would be determining binaries first and apply additional checks.
Report "firewall_active=${FIREWALL_ACTIVE}"
Report "firewall_empty_ruleset=${FIREWALL_EMPTY_RULESET}"
Report "firewall_installed=${FIREWALL_ACTIVE}"
WaitForKeyPress
#

View File

@ -18,7 +18,7 @@
#
#################################################################################
#
# Unsecure services
# Insecure services
#
#################################################################################
#
@ -28,32 +28,55 @@
#
INETD_ACTIVE=0
INETD_CONFIG_FILE="${ROOTDIR}etc/inetd.conf"
INETD_PACKAGE_INSTALLED=0
XINETD_ACTIVE=0
XINETD_CONFIG_FILE="${ROOTDIR}etc/xinetd.conf"
XINETD_CONFIG_DIR="${ROOTDIR}etc/xinetd.d"
#
#################################################################################
#
# Test : INSE-8000
# Description : Check for installed inetd package
Register --test-no INSE-8000 --weight L --network NO --category security --description "Installed inetd package"
if [ ${SKIPTEST} -eq 0 ]; then
# Check for installed inetd daemon
LogText "Test: Checking if inetd is installed"
if PackageIsInstalled "inetd"; then
INETD_PACKAGE_INSTALLED=1
LogText "Result: inetd is installed"
Display --indent 2 --text "- Installed inetd package" --result "${STATUS_FOUND}" --color YELLOW
#ReportSuggestion ${TEST_NO} "If there are no inetd services required, it is recommended that the daemon be removed"
else
LogText "Result: inetd is NOT installed"
Display --indent 2 --text "- Installed inetd package" --result "${STATUS_NOT_FOUND}" --color GREEN
fi
fi
#
#################################################################################
#
# Test : INSE-8002
# Description : Check for inetd status
Register --test-no INSE-8002 --weight L --network NO --category security --description "Check for enabled inet daemon"
if [ ${INETD_PACKAGE_INSTALLED} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no INSE-8002 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for enabled inet daemon"
if [ ${SKIPTEST} -eq 0 ]; then
# Check running processes
LogText "Test: Searching for active inet daemon"
IsRunning inetd
if [ ${RUNNING} -eq 1 ]; then
if IsRunning "inetd"; then
LogText "Result: inetd is running"
Display --indent 2 --text "- Checking inetd status" --result "ACTIVE" --color GREEN
Display --indent 4 --text "- inetd status" --result "ACTIVE" --color GREEN
INETD_ACTIVE=1
else
LogText "Result: inetd is NOT running"
Display --indent 2 --text "- Checking inetd status" --result "NOT ACTIVE" --color GREEN
Display --indent 4 --text "- inetd status" --result "NOT ACTIVE" --color GREEN
fi
fi
#
#################################################################################
#
# Test : INSE-8004
# Description : Check for inetd configuration file
# Description : Check for inetd configuration file (inetd)
if [ ${INETD_ACTIVE} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no INSE-8004 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for enabled inet daemon"
Register --test-no INSE-8004 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Presence of inetd configuration file"
if [ ${SKIPTEST} -eq 0 ]; then
# Check configuration file
LogText "Test: Searching for file ${INETD_CONFIG_FILE}"
@ -73,15 +96,15 @@
if [ ${INETD_ACTIVE} -eq 0 -a -f ${INETD_CONFIG_FILE} ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no INSE-8006 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check configuration of inetd when disabled"
if [ ${SKIPTEST} -eq 0 ]; then
# Check if any service is enabled in /etc/inetd.conf (inetd is not active, see test 8002)
LogText "Test: check if all services are disabled if inetd is disabled"
# Check if any service is enabled in /etc/inetd.conf (inetd is not active, see test INSE-8002)
LogText "Test: check if all services are disabled when inetd is disabled"
FIND=$(${GREPBINARY} -v "^#" ${INETD_CONFIG_FILE} | ${GREPBINARY} -v "^$")
if [ -z "${FIND}" ]; then
LogText "Result: no services found in ${INETD_CONFIG_FILE}"
Display --indent 4 --text "- Checking inetd.conf services" --result "${STATUS_OK}" --color GREEN
Display --indent 4 --text "- Checking enabled inetd services" --result "${STATUS_OK}" --color GREEN
else
LogText "Result: found services in inetd, even though inetd is not running"
Display --indent 4 --text "- Checking inetd.conf services" --result "${STATUS_SUGGESTION}" --color YELLOW
Display --indent 4 --text "- Checking enabled inetd services" --result "${STATUS_SUGGESTION}" --color YELLOW
ReportSuggestion ${TEST_NO} "Although inetd is not running, make sure no services are enabled in ${INETD_CONFIG_FILE}, or remove inetd service"
fi
fi
@ -95,7 +118,7 @@
if [ ${SKIPTEST} -eq 0 ]; then
LogText "Test: checking telnet presence in inetd configuration"
FIND=$(${GREPBINARY} "^telnet" ${INETD_CONFIG_FILE})
if [ "${FIND}" = "" ]; then
if [ -z "${FIND}" ]; then
LogText "Result: telnet not enabled in ${INETD_CONFIG_FILE}"
Display --indent 2 --text "- Checking inetd (telnet)" --result "${STATUS_NOT_FOUND}" --color GREEN
AddHP 3 3
@ -108,6 +131,289 @@
fi
#
#################################################################################
#
# Test : INSE-8100
# Description : Check for installed xinetd daemon
Register --test-no INSE-8100 --weight L --network NO --category security --description "Check for installed xinetd daemon"
if [ ${SKIPTEST} -eq 0 ]; then
# Check for installed xinetd daemon
LogText "Test: Checking for installed xinetd daemon"
if PackageIsInstalled "xinetd"; then
LogText "Result: xinetd is installed"
Display --indent 2 --text "- Installed xinetd package" --result "${STATUS_FOUND}" --color YELLOW
ReportSuggestion ${TEST_NO} "If there are no xinetd services required, it is recommended that the daemon be removed"
else
LogText "Result: xinetd is NOT installed"
Display --indent 2 --text "- Installed xinetd package" --result "${STATUS_OK}" --color GREEN
fi
fi
#
#################################################################################
#
# Test : INSE-8102
# Description : Check for xinetd status
Register --test-no INSE-8102 --weight L --network NO --category security --description "Check for active xinet daemon"
if [ ${SKIPTEST} -eq 0 ]; then
# Check running processes
LogText "Test: Searching for active extended internet services daemon (xinetd)"
if IsRunning "xinetd"; then
LogText "Result: xinetd is running"
Display --indent 4 --text "- xinetd status" --result "ACTIVE" --color GREEN
XINETD_ACTIVE=1
else
LogText "Result: xinetd is NOT running"
Display --indent 4 --text "- xinetd status" --result "NOT ACTIVE" --color GREEN
fi
fi
#
#################################################################################
#
# Test : INSE-8104
# Description : Check for xinetd configuration file
if [ ${XINETD_ACTIVE} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no INSE-8104 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for enabled xinet daemon"
if [ ${SKIPTEST} -eq 0 ]; then
# Check configuration file
LogText "Test: Searching for file ${XINETD_CONFIG_FILE}"
if [ -f "${XINETD_CONFIG_FILE}" ]; then
LogText "Result: ${XINETD_CONFIG_FILE} exists"
Display --indent 6 --text "- Configuration file (xinetd.conf)" --result "${STATUS_FOUND}" --color WHITE
else
LogText "Result: ${XINETD_CONFIG_FILE} does not exist"
Display --indent 6 --text "- Configuration file (xinetd.conf)" --result "${STATUS_NOT_FOUND}" --color WHITE
fi
fi
#
#################################################################################
#
# Test : INSE-8106
# Description : Check for xinetd configuration file contents if xinetd is NOT active
if [ ${XINETD_ACTIVE} -eq 0 -a -f ${XINETD_CONFIG_FILE} ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no INSE-8106 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check configuration of xinetd when disabled"
if [ ${SKIPTEST} -eq 0 ]; then
# Check if any service is enabled in /etc/xinetd.d (xinetd is not active, see test INSE-8102)
LogText "Test: check if all services are disabled if xinetd is disabled"
FIND=$(${GREPBINARY} -r "disable\s*=\s*no" ${XINETD_CONFIG_DIR})
if [ -z "${FIND}" ]; then
LogText "Result: no services found in ${XINETD_CONFIG_DIR}"
Display --indent 6 --text "- Enabled xinetd.d services" --result "${STATUS_NOT_FOUND}" --color GREEN
else
LogText "Result: found services in ${XINETD_CONFIG_DIR}, even though xinetd is not running"
Display --indent 6 --text "- Enabled xinetd.d services" --result "${STATUS_FOUND}" --color YELLOW
ReportSuggestion ${TEST_NO} "Although xinetd is not running, make sure no services are enabled in ${XINETD_CONFIG_DIR}, or remove xinetd service"
fi
fi
#
#################################################################################
#
# Test : INSE-8116
# Description : Check for insecure services enabled via xinetd
if [ ${XINETD_ACTIVE} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no INSE-8116 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Insecure services enabled via xinetd"
if [ ${SKIPTEST} -eq 0 ]; then
XINETD_INSECURE_SERVICE_FOUND=0
ITEMS="chargen chargen-dgram chargen-stream daytime daytime-dgram daytime-stream discard discard-dgram discard-stream echo echo-dgram echo-stream time time-dgram time-stream ntalk rexec rlogin rsh talk telnet tftp"
for SERVICE in ${ITEMS}; do
LogText "Test: checking service ${SERVICE}"
if ! SkipAtomicTest "${TEST_NO}:${SERVICE}"; then
FILE="${XINETD_CONFIG_DIR}/${SERVICE}"
if [ -f "${FILE}" ]; then
LogText "Test: checking status in xinetd configuration file (${FILE})"
FIND=$(${GREPBINARY} "disable\s*=\s*no" ${FILE})
if [ ! -z "${FIND}" ]; then
LogText "Result: found insecure service enabled: ${SERVICE}"
XINETD_INSECURE_SERVICE_FOUND=1
ReportSuggestion "${TEST_NO}" "Disable or remove any insecure services in the xinetd configuration" "${SERVICE}" "text:See log file for more details"
Report "insecure_service[]=${SERVICE}"
fi
fi
else
LogText "Result: skipped, as this item is excluded using the profile"
fi
done
if [ ${XINETD_INSECURE_SERVICE_FOUND} -eq 0 ]; then
LogText "Result: no insecure services found in xinetd configuration"
Display --indent 6 --text "- Checking xinetd (insecure services)" --result "${STATUS_OK}" --color GREEN
AddHP 3 3
else
LogText "Result: one ore more insecure services discovered in xinetd configuration"
Display --indent 6 --text "- Checking xinetd (insecure services)" --result "${STATUS_WARNING}" --color RED
AddHP 0 3
fi
fi
#
#################################################################################
#
# Test : INSE-8150
# Description : Check for rsync enabled via xinetd
#RSYNC_XINETD_CONFIG_FILE="${XINETD_CONFIG_DIR}/rsync"
#if [ ${XINETD_ACTIVE} -eq 1 -a -f ${RSYNC_XINETD_CONFIG_FILE} ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
#Register --test-no INSE-8150 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for rsync via xinetd"
#if [ ${SKIPTEST} -eq 0 ]; then
# LogText "Test: checking rsync presence in xinetd configuration"
# FIND=$(${GREPBINARY} "disable\s*=\s*no" ${RSYNC_XINETD_CONFIG_FILE})
# if [ "${FIND}" = "" ]; then
# LogText "Result: rsync not enabled in ${RSYNC_XINETD_CONFIG_FILE}"
# Display --indent 6 --text "- Checking xinetd (rsync)" --result "${STATUS_DISABLED}" --color GREEN
# else
# LogText "Result: rsync enabled in ${RSYNC_XINETD_CONFIG_FILE}"
# Display --indent 6 --text "- Checking xinetd (rsync)" --result "${STATUS_ENABLED}" --color RED
# ReportSuggestion "${TEST_NO}" "Disable rsync in xinetd configuration"
# fi
#fi
#
#################################################################################
#
# Test : INSE-8200
# Description : Check if tcp_wrappers is installed when inetd/xinetd is active
if [ ${INETD_ACTIVE} -eq 1 -o ${XINETD_ACTIVE} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no INSE-8200 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check if tcp_wrappers is installed when inetd/xinetd is active"
if [ ${SKIPTEST} -eq 0 ]; then
LogText "Test: Checking if tcp_wrappers is installed"
FOUND=0
PACKAGES="tcp_wrappers tcpd"
for PACKAGE in ${PACKAGES}; do
if PackageIsInstalled "${PACKAGE}"; then LogText "Package '${PACKAGE}' is installed"; FOUND=1; fi
done
if [ ${FOUND} -eq 1 ]; then
LogText "Result: tcp_wrappers is installed"
Display --indent 2 --text "- Checking tcp_wrappers installation" --result "${STATUS_OK}" --color GREEN
else
LogText "Result: tcp_wrappers is NOT installed"
Display --indent 2 --text "- Checking tcp_wrappers installation" --result "${STATUS_SUGGESTION}" --color YELLOW
#ReportSuggestion ${TEST_NO} "When network services are using the inetd/xinetd service, the tcp_wrappers package should be installed"
fi
fi
#
#################################################################################
#
# Test : INSE-8300
# Description : Check if rsh client is installed
Register --test-no INSE-8300 --weight L --network NO --category security --description "Check if rsh client is installed"
if [ ${SKIPTEST} -eq 0 ]; then
LogText "Test: Checking if rsh client is installed"
FOUND=0
PACKAGES="rsh rsh-client rsh-redone-client"
for PACKAGE in ${PACKAGES}; do
if PackageIsInstalled "${PACKAGE}"; then LogText "Package '${PACKAGE}' is installed"; FOUND=1; fi
done
if [ ${FOUND} -eq 1 ]; then
LogText "Result: rsh client is installed"
Display --indent 2 --text "- Installed rsh client package" --result "${STATUS_SUGGESTION}" --color YELLOW
ReportSuggestion ${TEST_NO} "Remove rsh client when it is not in use or replace with the more secure SSH package"
else
LogText "Result: rsh client is NOT installed"
Display --indent 2 --text "- Installed rsh client package" --result "${STATUS_OK}" --color GREEN
fi
fi
#
#################################################################################
#
# Test : INSE-8302
# Description : Check presence of rsh Trust Files
#Register --test-no INSE-8302 --weight L --network NO --category security --description "Check presence of rsh Trust Files"
#if [ ${SKIPTEST} -eq 0 ]; then
# # Check presence of Rsh Trust Files
# FOUND=0
# for LINE in $(${CAT_BINARY} /etc/passwd | ${EGREPBINARY} -v '^(root|halt|sync|shutdown)' | ${AWKBINARY} -F: '($7 !="/sbin/nologin" && $7 != "/bin/false") { print }'); do
# USER=$(echo ${LINE} | ${CUTBINARY} -d: -f1)
# DIR=$(echo ${LINE} | ${CUTBINARY} -d: -f6)
# if [ -d ${DIR} ]; then
# for RHOSTS in ${DIR}/.rhosts; do
# if [ ! -h ${RHOSTS} -a -f ${RHOSTS} ]; then
# LogText "FOUND .rhosts file in home directory ${DIR} of ${USER}"
# FOUND=1
# fi
# done
# fi
# done
# if [ -f /etc/hosts.equiv ];then
# LogText "FOUND /etc/hosts.equiv"
# FOUND=1
# fi
# if [ ${FOUND} -eq 1 ]; then
# LogText "Result: found one or more Rsh Trust Files"
# Display --indent 4 --text "- Checking presence of Rsh Trust Files" --result "${STATUS_SUGGESTION}" --color YELLOW
# ReportSuggestion ${TEST_NO} "Remove every Rsh Trust Files as they can allow unauthenticated access to a system"
# else
# LogText "Result: no Rsh Trust Files found"
# Display --indent 4 --text "- Checking presence of Rsh Trust Files" --result "${STATUS_OK}" --color GREEN
# fi
#fi
#
#################################################################################
#
# Test : INSE-8304
# Description : Check if rsh server is installed
Register --test-no INSE-8342 --weight L --network NO --category security --description "Check if rsh server is installed"
if [ ${SKIPTEST} -eq 0 ]; then
# Check if rsh server is installed
LogText "Test: Checking if rsh server is installed"
FOUND=0
PACKAGES="rsh-server rsh-redone-server"
for PACKAGE in ${PACKAGES}; do
if PackageIsInstalled "${PACKAGE}"; then LogText "Package '${PACKAGE}' is installed"; FOUND=1; fi
done
if [ ${FOUND} -eq 1 ]; then
LogText "Result: rsh server is installed"
Display --indent 2 --text "- Installed rsh server package" --result "${STATUS_SUGGESTION}" --color YELLOW
ReportSuggestion ${TEST_NO} "Remove the rsh-server package and replace with a more secure alternative like SSH"
Report "insecure_service[]=rsh-server"
else
LogText "Result: rsh server is NOT installed"
Display --indent 2 --text "- Installed rsh server package" --result "${STATUS_OK}" --color GREEN
fi
fi
#
#################################################################################
#
# Test : INSE-8310
# Description : Check if telnet client is installed
Register --test-no INSE-8310 --weight L --network NO --category security --description "Check if telnet client is installed"
if [ ${SKIPTEST} -eq 0 ]; then
# Check if telnet client is installed
LogText "Test: Checking if telnet client is installed"
if PackageIsInstalled "${PACKAGE}"; then LogText "Package '${PACKAGE}' is installed"; FOUND=1; fi
if [ ${FOUND} -eq 1 ]; then
LogText "Result: telnet client is installed"
Display --indent 2 --text "- Installed telnet client package" --result "${STATUS_FOUND}" --color YELLOW
# Telnet client usage might be used for troubleshooting instead of system administration
#ReportSuggestion ${TEST_NO} "telnet client contain numerous security exposures and have been replaced with the more secure SSH package"
else
LogText "Result: telnet client is NOT installed"
Display --indent 2 --text "- Installed telnet client package" --result "${STATUS_OK}" --color GREEN
fi
fi
#
#################################################################################
#
# Test : INSE-8312
# Description : Check if telnet server is installed
Register --test-no INSE-8322 --weight L --network NO --category security --description "Check if telnet server is installed"
if [ ${SKIPTEST} -eq 0 ]; then
# Check if TFTP server is installed
LogText "Test: Checking if telnet server is installed"
FOUND=0
PACKAGES="telnetd telnet-server"
for PACKAGE in ${PACKAGES}; do
if PackageIsInstalled "${PACKAGE}"; then LogText "Package '${PACKAGE}' is installed"; FOUND=1; fi
done
if [ ${FOUND} -eq 1 ]; then
LogText "Result: telnet server is installed"
Display --indent 2 --text "- Installed telnet server package" --result "${STATUS_FOUND}" --color YELLOW
ReportSuggestion ${TEST_NO} "Removing the ${FOUND} package and replace with SSH when possible"
Report "insecure_service[]=telnet-server"
else
LogText "Result: telnet server is NOT installed"
Display --indent 2 --text "- Installed telnet server package" --result "${STATUS_NOT_FOUND}" --color GREEN
fi
fi
#
#################################################################################
#
if [ ! -z "${LAUNCHCTL_BINARY}" ]; then PREQS_MET="YES"; SKIPREASON=""; else PREQS_MET="NO"; SKIPREASON="No launchctl binary on this system"; fi
Register --test-no INSE-8050 --os "macOS" --preqs-met ${PREQS_MET} --skip-reason "${SKIPREASON}" --weight M --network NO --category security --description "Check for insecure services on macOS"

View File

@ -30,17 +30,17 @@
# Description : Query /proc/meminfo
Register --test-no PROC-3602 --os Linux --weight L --network NO --category security --description "Checking /proc/meminfo for memory details"
if [ ${SKIPTEST} -eq 0 ]; then
if [ -f /proc/meminfo ]; then
LogText "Result: found /proc/meminfo"
Display --indent 2 --text "- Checking /proc/meminfo" --result "${STATUS_FOUND}" --color GREEN
FIND=$(${AWKBINARY} '/^MemTotal/ { print $2, $3 }' /proc/meminfo)
if [ -f ${ROOTDIR}proc/meminfo ]; then
LogText "Result: found ${ROOTDIR}proc/meminfo"
Display --indent 2 --text "- Checking ${ROOTDIR}proc/meminfo" --result "${STATUS_FOUND}" --color GREEN
FIND=$(${AWKBINARY} '/^MemTotal/ { print $2, $3 }' ${ROOTDIR}proc/meminfo)
MEMORY_SIZE=$(echo ${FIND} | ${AWKBINARY} '{ print $1 }')
MEMORY_UNITS=$(echo ${FIND} | ${AWKBINARY} '{ print $2 }')
LogText "Result: Found ${MEMORY_SIZE} ${MEMORY_UNITS} memory"
Report "memory_size=${MEMORY_SIZE}"
Report "memory_units=${MEMORY_UNITS}"
else
LogText "Result: /proc/meminfo file not found on this system"
LogText "Result: ${ROOTDIR}proc/meminfo file not found on this system"
fi
fi
#
@ -80,7 +80,7 @@
fi
if [ -z "${FIND}" ]; then
LogText "Result: no zombie processes found"
Display --indent 2 --text "- Searching for dead/zombie processes" --result "${STATUS_OK}" --color GREEN
Display --indent 2 --text "- Searching for dead/zombie processes" --result "${STATUS_NOT_FOUND}" --color GREEN
else
LogText "Result: found one or more dead or zombie processes"
LogText "Output: PIDs ${FIND}"
@ -104,7 +104,7 @@
fi
if [ -z "${FIND}" ]; then
LogText "Result: No processes were waiting for IO requests to be handled first"
Display --indent 2 --text "- Searching for IO waiting processes" --result "${STATUS_OK}" --color GREEN
Display --indent 2 --text "- Searching for IO waiting processes" --result "${STATUS_NOT_FOUND}" --color GREEN
else
LogText "Result: found one or more processes which were waiting to get IO requests handled first"
LogText "More info: processes which show up with the status flag 'D' are often stuck, until a disk IO event finished. This can happen for example with network storage, where the connection or protocol settings are not logtext well configured."
@ -116,6 +116,27 @@
#
#################################################################################
#
# Test : PROC-3802
# Description : Check presence of prelink tooling
Register --test-no PROC-3802 --weight L --network NO --category security --description "Check presence of prelink tooling"
if [ ${SKIPTEST} -eq 0 ]; then
if PackageIsInstalled "prelink"; then
LogText "Result: prelink packages is installed"
# TODO
# - Add item to website with rationale
#ReportSuggestion "${TEST_NO}" "Disable and remove prelinking of binaries"
AddHP 1 3
Display --indent 2 --text "- Search prelink tooling" --result "${STATUS_FOUND}" --color YELLOW
else
Display --indent 2 --text "- Search prelink tooling" --result "${STATUS_NOT_FOUND}" --color GREEN
LogText "Result: prelink package is NOT installed"
AddHP 3 3
fi
fi
#
#################################################################################
#
WaitForKeyPress

View File

@ -644,15 +644,15 @@
if [ "${FIND}" = "127.0.0.1" ]; then
LogText "Result: localhost mapped to 127.0.0.1"
Display --indent 4 --text "- Checking /etc/hosts (localhost to IP)" --result "${STATUS_OK}" --color GREEN
report "localhost-mapped-to=${FIND}"
Report "localhost-mapped-to=${FIND}"
elif [ "${FIND}" = "::1" ]; then
LogText "Result: localhost mapped to ::1"
Display --indent 4 --text "- Checking /etc/hosts (localhost to IP)" --result "${STATUS_OK}" --color GREEN
report "localhost-mapped-to=${FIND}"
Report "localhost-mapped-to=${FIND}"
elif [ "${FIND}" = "127.0.0.1::1" ]; then
LogText "Result: localhost mapped to 127.0.0.1 and ::1"
Display --indent 4 --text "- Checking /etc/hosts (localhost to IP)" --result "${STATUS_OK}" --color GREEN
report "localhost-mapped-to=${FIND}"
Report "localhost-mapped-to=${FIND}"
else
LogText "Output: ${FIND}"
LogText "Result: this server hostname is not mapped to a local address"

View File

@ -370,6 +370,7 @@
# Description : Check listening ports
Register --test-no NETW-3012 --weight L --network NO --category security --description "Check listening ports"
if [ ${SKIPTEST} -eq 0 ]; then
DATA=""
FIND=""; FIND2=""
COUNT=0
case ${OS} in
@ -381,24 +382,19 @@
FIND=""
fi
FIND2=""
;;
;;
Linux)
if [ ! -z "${NETSTATBINARY}" ]; then
if [ -n "${SSBINARY}" ]; then
DATA=$(${SSBINARY} --query=udp,tcp -plnt | awk '{ if ($1!="Netid") { print "raw,ss,v1|"$1"|"$5"|"$7"|" }}' | sed 's/pid=[0-9]\{1,\},fd=[0-9]\{1,\}//g' | sed 's/users://' | sed 's/,)//g' | tr -d '()"')
elif [ -n "${NETSTATBINARY}" ]; then
# UDP
FIND=$(${NETSTATBINARY} -nlp 2> /dev/null | ${GREPBINARY} "^udp" | ${AWKBINARY} '{ print $4"|"$1"|"$6"|" }' | ${SEDBINARY} 's:|[0-9]*/:|:')
# TCP
FIND2=$(${NETSTATBINARY} -nlp 2> /dev/null | ${GREPBINARY} "^tcp" | ${AWKBINARY} '{ if($6=="LISTEN") { print $4"|"$1"|"$7"|" }}' | ${SEDBINARY} 's:|[0-9]*/:|:')
else
if [ ! "${SSBINARY}" = "" ]; then
# UDP
FIND=$(${SSBINARY} -u -a -n 2> /dev/null | ${AWKBINARY} '{ print $4 }' | ${GREPBINARY} -v Local)
# TCP
FIND2=$(${SSBINARY} -t -a -n 2> /dev/null | ${AWKBINARY} '{ print $4 }' | ${GREPBINARY} -v Local)
else
ReportException "${TEST_NO}:1" "netstat and ss binary missing to gather listening ports"
fi
ReportException "${TEST_NO}:1" "netstat and ss binary missing to gather listening ports"
fi
;;
;;
macOS)
if [ ! "${LSOFBINARY}" = "" ]; then
@ -409,9 +405,7 @@
fi
# Not needed as we have a combined test
FIND2=""
;;
;;
NetBSD)
if [ ! "${SOCKSTATBINARY}" = "" ]; then
FIND=$(${SOCKSTATBINARY} 2> /dev/null | ${AWKBINARY} '{ if ($7 ~ /\*.\*/) print $5"|"$6"|"$2"|" }' | ${SORTBINARY} -u)
@ -419,7 +413,7 @@
FIND=""
fi
FIND2=""
;;
;;
OpenBSD)
if [ ! "${NETSTATBINARY}" = "" ]; then
# UDP
@ -429,13 +423,20 @@
else
ReportException "${TEST_NO}:3" "netstat missing to gather listening ports"
fi
;;
;;
*)
# Got this exception? Provide your details and output of netstat or any other tool to determine this information.
ReportException "${TEST_NO}:2" "Unclear what method to use, to determine listening port information"
;;
;;
esac
if HasData "${DATA}"; then
for ITEM in ${DATA}; do
COUNT=$((COUNT + 1))
Report "network_listen[]=${ITEM}"
done
fi
# Retrieve information from sockstat, when available
LogText "Test: Retrieving sockstat information to find listening ports"
if HasData "${FIND}"; then
@ -453,11 +454,10 @@
Report "network_listen_port[]=${ITEM}"
done
fi
if [ "${FIND}" = "" -a "${FIND2}" = "" ]; then
if [ -z "${DATA}" -a -z "${FIND}" ]; then
Display --indent 2 --text "- Getting listening ports (TCP/UDP)" --result "${STATUS_SKIPPED}" --color YELLOW
else
Display --indent 2 --text "- Getting listening ports (TCP/UDP)" --result "${STATUS_DONE}" --color GREEN
Display --indent 6 --text "* Found ${COUNT} ports"
fi
fi
#
@ -610,33 +610,34 @@
if [ ${SKIPTEST} -eq 0 ]; then
FOUND=0
# addrwatch
if IsRunning "addrwatch"; then
FOUND=1
fi
# arpwatch
IsRunning arpwatch
if [ ${RUNNING} -eq 1 ]; then
if IsRunning "arpwatch"; then
FOUND=1
ARPWATCH_RUNNING=1
Display --indent 2 --text "- Checking for ARP monitoring software" --result "${STATUS_RUNNING}" --color GREEN
fi
# arpon
IsRunning arpon
if [ ${RUNNING} -eq 1 ]; then
if IsRunning "arpon"; then
FOUND=1
ARPON_RUNNING=1
Display --indent 2 --text "- Checking for ARP monitoring software" --result "${STATUS_RUNNING}" --color GREEN
fi
if [ ${FOUND} -eq 0 ]; then
if [ ${FOUND} -eq 1 ]; then
Display --indent 2 --text "- Checking for ARP monitoring software" --result "${STATUS_RUNNING}" --color GREEN
else
Display --indent 2 --text "- Checking for ARP monitoring software" --result "${STATUS_NOT_FOUND}" --color YELLOW
ReportSuggestion ${TEST_NO} "Consider running ARP monitoring software (arpwatch,arpon)"
ReportSuggestion "${TEST_NO}" "Consider running ARP monitoring software (addrwatch,arpwatch,arpon)"
fi
fi
#
#################################################################################
#
Report "dhcp_client_running=${DHCP_CLIENT_RUNNING}"
Report "arpwatch_running=${ARPWATCH_RUNNING}"
WaitForKeyPress
#

View File

@ -42,6 +42,9 @@
${ROOTDIR}etc/php5/apache2/php.ini \
${ROOTDIR}etc/php5/fpm/php.ini \
${ROOTDIR}private/etc/php.ini \
${ROOTDIR}etc/php/7.2/apache2/php.ini \
${ROOTDIR}etc/php/7.1/apache2/php.ini \
${ROOTDIR}etc/php/7.0/apache2/php.ini \
${ROOTDIR}etc/php/7.2/cli/php.ini ${ROOTDIR}etc/php/7.2/fpm/php.ini \
${ROOTDIR}etc/php/7.1/cli/php.ini ${ROOTDIR}etc/php/7.1/fpm/php.ini \
${ROOTDIR}etc/php/7.0/cli/php.ini ${ROOTDIR}etc/php/7.0/fpm/php.ini \

View File

@ -344,7 +344,7 @@
COUNT=0
PACKAGE_AUDIT_TOOL_FOUND=1
PACKAGE_AUDIT_TOOL="zypper"
FIND=$(${ZYPPERBINARY} -n se -t package -i | ${AWKBINARY} '{ if ($1=="i") { print $3 } }')
FIND=$(${ZYPPERBINARY} --non-interactive -n se -t package -i | ${AWKBINARY} '{ if ($1=="i") { print $3 } }')
if [ ! -z "${FIND}" ]; then
for PKG in ${FIND}; do
COUNT=$((COUNT + 1))
@ -365,7 +365,7 @@
if [ ! -z "${ZYPPERBINARY}" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no PKGS-7330 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Querying Zypper for vulnerable packages"
if [ ${SKIPTEST} -eq 0 ]; then
FIND=$(${ZYPPERBINARY} -n pchk | ${GREPBINARY} "(0 security patches)")
FIND=$(${ZYPPERBINARY} --non-interactive pchk | ${GREPBINARY} "(0 security patches)")
if [ ! -z "${FIND}" ]; then
LogText "Result: No security updates found with Zypper"
Display --indent 2 --text "- Using Zypper to find vulnerable packages" --result "${STATUS_NONE}" --color GREEN
@ -374,7 +374,7 @@
LogText "Result: Zypper found one or more installed packages which are vulnerable."
ReportWarning ${TEST_NO} "Found one or more vulnerable packages installed"
# Unfortunately zypper does not properly give back which package it is. Usually best guess is last word on the line
FIND=$(${ZYPPERBINARY} -n lp | ${AWKBINARY} '{ if ($5=="security" || $7=="security") { print $NF }}' | ${SEDBINARY} 's/:$//' | ${GREPBINARY} -v "^$" | ${SORTBINARY} -u)
FIND=$(${ZYPPERBINARY} --non-interactive lp | ${AWKBINARY} '{ if ($5=="security" || $7=="security") { print $NF }}' | ${SEDBINARY} 's/:$//' | ${GREPBINARY} -v "^$" | ${SORTBINARY} -u)
LogText "List of vulnerable packages/version:"
for PKG in ${FIND}; do
VULNERABLE_PACKAGES_FOUND=1
@ -879,8 +879,7 @@
if [ ${DO_TEST} -eq 0 ]; then
FileExists ${ROOTDIR}usr/share/yum-cli/cli.py
if [ ${FILE_FOUND} -eq 1 ]; then
SearchItem "\-\-security" "${ROOTDIR}usr/share/yum-cli/cli.py"
if [ ${ITEM_FOUND} -eq 1 ]; then
if SearchItem "\-\-security" "${ROOTDIR}usr/share/yum-cli/cli.py"; then
DO_TEST=1
LogText "Result: found built-in security in yum"
else
@ -892,8 +891,7 @@
if [ ${DO_TEST} -eq 0 ]; then
FileExists ${ROOTDIR}etc/yum/pluginconf.d/security.conf
if [ ${FILE_FOUND} -eq 1 ]; then
SearchItem "^enabled=1$" "${ROOTDIR}etc/yum/pluginconf.d/security.conf"
if [ ${ITEM_FOUND} -eq 1 ]; then
if SearchItem "^enabled=1$" "${ROOTDIR}etc/yum/pluginconf.d/security.conf"; then
DO_TEST=1
LogText "Result: found enabled plugin"
else
@ -930,7 +928,6 @@
AddHP 1 2
done
ReportWarning ${TEST_NO} "Found one or more vulnerable packages."
ReportSuggestion ${TEST_NO} "Use 'yum --security update' to update your system"
fi
else
LogText "Result: yum-security package not found"
@ -968,8 +965,8 @@
FOUND=0
FileExists ${ROOTDIR}etc/yum.conf
if [ ${FILE_FOUND} -eq 1 ]; then
SearchItem "^gpgenabled\s*=\s*1$" "${ROOTDIR}etc/yum.conf"; if [ ${ITEM_FOUND} -eq 1 ]; then FOUND=1; fi
SearchItem "^gpgcheck\s*=\s*1$" "${ROOTDIR}etc/yum.conf"; if [ ${ITEM_FOUND} -eq 1 ]; then FOUND=1; fi
if SearchItem "^gpgenabled\s*=\s*1$" "${ROOTDIR}etc/yum.conf"; then FOUND=1; fi
if SearchItem "^gpgcheck\s*=\s*1$" "${ROOTDIR}etc/yum.conf"; then FOUND=1; fi
if [ ${FOUND} -eq 1 ]; then
LogText "Result: GPG check is enabled"
Display --indent 2 --text "- Checking GPG checks (yum.conf)" --result "${STATUS_OK}" --color GREEN
@ -1055,7 +1052,8 @@
#
# Test : PKGS-7392
# Description : Check Debian/Ubuntu vulnerable packages
if [ -x ${ROOTDIR}usr/bin/apt-get ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
# Note : Skip for zypper-based systems
if [ -x ${ROOTDIR}usr/bin/apt-get -a -z "${ZYPPERBINARY}" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no PKGS-7392 --os Linux --preqs-met ${PREQS_MET} --root-only YES --weight L --network YES --category security --description "Check for Debian/Ubuntu security updates"
if [ ${SKIPTEST} -eq 0 ]; then
VULNERABLE_PACKAGES_FOUND=0
@ -1247,8 +1245,20 @@
Register --test-no PKGS-7410 --weight L --network NO --category security --description "Count installed kernel packages"
if [ ${SKIPTEST} -eq 0 ]; then
KERNELS=0
if [ ! -z "${RPMBINARY}" ]; then
LogText "Test: Checking how many kernel packages are installed"
LogText "Test: Checking how many kernel packages are installed"
if [ ! -z "${DPKGBINARY}" ]; then
KERNELS=$(${DPKGBINARY} -l 2> /dev/null | ${GREPBINARY} "linux-image-[0-9]" | ${WCBINARY} -l)
if [ ${KERNELS} -eq 0 ]; then
LogText "Result: found no kernels from dpkg -l output, which is unexpected"
ReportException "KRNL-5840:2" "Could not find any kernel packages from DPKG output"
elif [ ${KERNELS} -gt 5 ]; then
LogText "Result: found more than 5 kernel packages on the system, which might indicate lack of regular cleanups"
ReportSuggestion "${TEST_NO}" "Remove any unneeded kernel packages" "${KERNELS} kernels" "text:validate dpkg -l output and perform cleanup with apt autoremove"
else
LogText "Result: found ${KERNELS} kernel packages on the system, which is fine"
fi
elif [ ! -z "${RPMBINARY}" ]; then
KERNELS=$(${RPMBINARY} -q kernel 2> /dev/null | ${WCBINARY} -l)
if [ ${KERNELS} -eq 0 ]; then
LogText "Result: found no kernels from rpm -q kernel output, which is unexpected"
@ -1256,22 +1266,77 @@
elif [ ${KERNELS} -gt 5 ]; then
LogText "Result: found more than 5 kernel packages on the system, which might indicate lack of regular cleanups"
ReportSuggestion "${TEST_NO}" "Remove any unneeded kernel packages with package-cleanup utility (--old-kernels)"
AddHP 4 5
else
LogText "Result: found ${KERNELS} on the system, which is fine"
AddHP 1 1
LogText "Result: found ${KERNELS} kernel packages on the system, which is fine"
fi
fi
Report "installed_kernel_packages=${KERNELS}"
fi
#
#################################################################################
#
# Test : PKGS-7420
# Description : Detect toolkit to automatically download and apply upgrades
Register --test-no PKGS-7420 --weight L --network NO --category security --description "Detect toolkit to automatically download and apply upgrades"
if [ ${SKIPTEST} -eq 0 ]; then
UNATTENDED_UPGRADES_TOOLKIT=0
UNATTENDED_UPGRADES_TOOL=""
UNATTENDED_UPGRADES_OPTION_AVAILABLE=0
if [ ! -z "${INSTALLED_PACKAGES}" ]; then Report "installed_packages_array=${INSTALLED_PACKAGES}"; fi
case "${OS}" in
"Linux")
case "${LINUX_VERSION}" in
"CentOS" | "Debian" | "Fedora" | "RHEL" | "Ubuntu")
Report "package_audit_tool=${PACKAGE_AUDIT_TOOL}"
Report "package_audit_tool_found=${PACKAGE_AUDIT_TOOL_FOUND}"
Report "vulnerable_packages_found=${VULNERABLE_PACKAGES_FOUND}"
UNATTENDED_UPGRADES_OPTION_AVAILABLE=1
# Test available tools for Linux
if [ -f "${ROOTDIR}bin/auter" ]; then
UNATTENDED_UPGRADES_TOOL="auter"
UNATTENDED_UPGRADES_TOOLKIT=1
LogText "Result: found ${UNATTENDED_UPGRADES_TOOL}"
Report "unattended_upgrade_tool[]=${UNATTENDED_UPGRADES_TOOL}"
fi
if [ -f "${ROOTDIR}sbin/yum-cron" ]; then
UNATTENDED_UPGRADES_TOOL="yum-cron"
UNATTENDED_UPGRADES_TOOLKIT=1
LogText "Result: found ${UNATTENDED_UPGRADES_TOOL}"
Report "unattended_upgrade_tool[]=${UNATTENDED_UPGRADES_TOOL}"
fi
if [ -f "${ROOTDIR}usr/bin/dnf-automatic" ]; then
UNATTENDED_UPGRADES_TOOL="dnf-automatic"
UNATTENDED_UPGRADES_TOOLKIT=1
LogText "Result: found ${UNATTENDED_UPGRADES_TOOL}"
Report "unattended_upgrade_tool[]=${UNATTENDED_UPGRADES_TOOL}"
fi
if [ -f "${ROOTDIR}usr/bin/unattended-upgrade" ]; then
UNATTENDED_UPGRADES_TOOL="unattended-upgrade"
UNATTENDED_UPGRADES_TOOLKIT=1
LogText "Result: found ${UNATTENDED_UPGRADES_TOOL}"
Report "unattended_upgrade_tool[]=${UNATTENDED_UPGRADES_TOOL}"
fi
;;
esac
;;
esac
if [ ${UNATTENDED_UPGRADES_OPTION_AVAILABLE} -eq 1 ]; then
if [ ${UNATTENDED_UPGRADES_TOOLKIT} -eq 1 ]; then
AddHP 5 5
Display --indent 2 --text "- Toolkit for automatic upgrades (${UNATTENDED_UPGRADES_TOOL})" --result "${STATUS_FOUND}" --color GREEN
else
AddHP 1 5
Display --indent 2 --text "- Toolkit for automatic upgrades" --result "${STATUS_NOTFOUND}" --color YELLOW
LogText "Result: no toolkit for automatic updates discovered"
ReportSuggestion "${TEST_NO}" "Consider using a tool to automatically apply upgrades"
fi
fi
Report "unattended_upgrade_option_available=${UNATTENDED_UPGRADES_OPTION_AVAILABLE}"
fi
#
#################################################################################
#
WaitForKeyPress

View File

@ -31,9 +31,10 @@
# Files (interactive login shells): /etc/profile $HOME/.bash_profile
# $HOME/.bash_login $HOME/.profile
# Files (interactive non-login shells): $HOME/.bash_rc
#
# csh/tcsh
# Files: /etc/csh.cshrc /etc/csh.login
#
# zsh
# Files: /etc/zshenv /etc/zsh/zshenv $HOME/.zshenv /etc/zprofile
# /etc/zsh/zprofile $HOME/.zprofile /etc/zshrc /etc/zsh/zshrc
@ -68,8 +69,8 @@
#################################################################################
#
# Test : SHLL-6211
# Description : which shells are available according /etc/shells
Register --test-no SHLL-6211 --weight L --network NO --category security --description "Checking available and valid shells"
# Description : Determine available shell according /etc/shells
Register --test-no SHLL-6211 --weight L --network NO --category security --description "Available and valid shells"
if [ ${SKIPTEST} -eq 0 ]; then
LogText "Test: Searching for ${ROOTDIR}etc/shells"
if [ -f ${ROOTDIR}etc/shells ]; then
@ -98,8 +99,8 @@
#################################################################################
#
# Test : SHLL-6220
# Description : check for idle session killing tools or settings
Register --test-no SHLL-6220 --weight L --network NO --category security --description "Checking available and valid shells"
# Description : Check for idle session killing tools or settings
Register --test-no SHLL-6220 --weight L --network NO --category security --description "Idle session killing tools or settings"
if [ ${SKIPTEST} -eq 0 ]; then
IDLE_TIMEOUT_METHOD=""

View File

@ -27,6 +27,7 @@
SSH_DAEMON_PORT=""
SSH_DAEMON_RUNNING=0
SSH_DAEMON_OPTIONS_FILE=""
OPENSSHD_RUNNING=0
OPENSSHD_VERSION=0
OPENSSHD_VERSION_MAJOR=0
OPENSSHD_VERSION_MINOR=0
@ -42,8 +43,8 @@
Register --test-no SSH-7402 --weight L --network NO --category security --description "Check for running SSH daemon"
if [ ${SKIPTEST} -eq 0 ]; then
LogText "Test: Searching for a SSH daemon"
IsRunning sshd
if [ ${RUNNING} -eq 1 ] || PortIsListening "TCP" 22; then
if IsRunning "sshd"; then
OPENSSHD_RUNNING=1
SSH_DAEMON_RUNNING=1
Display --indent 2 --text "- Checking running SSH daemon" --result "${STATUS_FOUND}" --color GREEN
# Store settings in a temporary file
@ -51,6 +52,9 @@
SSH_DAEMON_OPTIONS_FILE="${TEMP_FILE}"
# Use a non-existing user, to ensure that systems that have a Match block configured, will be evaluated as well
${SSHDBINARY} -T -C user=doesnotexist,host=none,addr=none 2> /dev/null > ${SSH_DAEMON_OPTIONS_FILE}
elif PortIsListening "TCP" 22; then
Display --indent 2 --text "- Checking running SSH daemon" --result "${STATUS_FOUND}" --color GREEN
SSH_DAEMON_RUNNING=1
else
Display --indent 2 --text "- Checking running SSH daemon" --result "${STATUS_NOT_FOUND}" --color WHITE
fi
@ -60,7 +64,7 @@
#
# Test : SSH-7404
# Description : Determine SSH daemon configuration file location
if [ ${SSH_DAEMON_RUNNING} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
if [ ${OPENSSHD_RUNNING} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no SSH-7404 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check SSH daemon file location"
if [ ${SKIPTEST} -eq 0 ]; then
FOUND=0
@ -95,7 +99,7 @@
#
# Test : SSH-7406
# Description : Check OpenSSH version
if [ ${SSH_DAEMON_RUNNING} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
if [ ${OPENSSHD_RUNNING} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no SSH-7406 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Determine OpenSSH version"
if [ ${SKIPTEST} -eq 0 ]; then
OPENSSHD_VERSION=$(${SSHDBINARY} -t -d 2>&1 | ${GREPBINARY} 'sshd version' | ${AWKBINARY} '{if($4~OpenSSH_){print $4}}' | ${AWKBINARY} -F_ '{print $2}' | ${TRBINARY} -d ',' | ${TRBINARY} -d '\r')
@ -113,7 +117,7 @@
# Test : SSH-7408
# Description : Check SSH specific defined options
# Notes : Instead of parsing the configuration file, we query the SSH daemon itself
if [ ${SSH_DAEMON_RUNNING} -eq 1 -a ! -z "${SSH_DAEMON_OPTIONS_FILE}" -a ${OPENSSHD_VERSION_MAJOR} -ge 5 -a ${OPENSSHD_VERSION_MINOR} -ge 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
if [ ${OPENSSHD_RUNNING} -eq 1 -a ! -z "${SSH_DAEMON_OPTIONS_FILE}" -a ${OPENSSHD_VERSION_MAJOR} -ge 5 -a ${OPENSSHD_VERSION_MINOR} -ge 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no SSH-7408 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check SSH specific defined options"
if [ ${SKIPTEST} -eq 0 ]; then
LogText "Test: Checking specific defined options in ${SSH_DAEMON_OPTIONS_FILE}"
@ -258,31 +262,31 @@
fi
if [ "${RESULT}" = "GOOD" ]; then
LogText "Result: SSH option ${OPTIONNAME} is configured very well"
Display --indent 4 --text "- SSH option: ${OPTIONNAME}" --result "${STATUS_OK}" --color GREEN
LogText "Result: OpenSSH option ${OPTIONNAME} is configured very well"
Display --indent 4 --text "- OpenSSH option: ${OPTIONNAME}" --result "${STATUS_OK}" --color GREEN
AddHP 3 3
elif [ "${RESULT}" = "MIDSCORED" ]; then
LogText "Result: SSH option ${OPTIONNAME} is configured reasonably"
LogText "Result: OpenSSH option ${OPTIONNAME} is configured reasonably"
ReportSuggestion ${TEST_NO} "Consider hardening SSH configuration" "${OPTIONNAME} (${FOUNDVALUE} --> ${EXPECTEDVALUE})" "-"
ReportDetails --test "${TEST_NO}" --service "sshd" --field "${OPTIONNAME}" --value "${FOUNDVALUE}" --preferredvalue "${EXPECTEDVALUE}" --description "sshd option ${OPTIONNAME}"
Display --indent 4 --text "- SSH option: ${OPTIONNAME}" --result "${STATUS_SUGGESTION}" --color YELLOW
Display --indent 4 --text "- OpenSSH option: ${OPTIONNAME}" --result "${STATUS_SUGGESTION}" --color YELLOW
AddHP 1 3
elif [ "${RESULT}" = "WEAK" ]; then
LogText "Result: SSH option ${OPTIONNAME} is in a weak configuration state and should be fixed"
LogText "Result: OpenSSH option ${OPTIONNAME} is in a weak configuration state and should be fixed"
ReportSuggestion ${TEST_NO} "Consider hardening SSH configuration" "${OPTIONNAME} (${FOUNDVALUE} --> ${EXPECTEDVALUE})" "-"
ReportDetails --test "${TEST_NO}" --service "sshd" --field "${OPTIONNAME}" --value "${FOUNDVALUE}" --preferredvalue "${EXPECTEDVALUE}" --description "sshd option ${OPTIONNAME}"
Display --indent 4 --text "- SSH option: ${OPTIONNAME}" --result "${STATUS_SUGGESTION}" --color YELLOW
Display --indent 4 --text "- OpenSSH option: ${OPTIONNAME}" --result "${STATUS_SUGGESTION}" --color YELLOW
AddHP 0 3
elif [ "${RESULT}" = "UNKNOWN" ]; then
LogText "Result: Value of SSH option ${OPTIONNAME} is unknown (not defined)"
Display --indent 4 --text "- SSH option: ${OPTIONNAME}" --result DEFAULT --color WHITE
LogText "Result: Value of OpenSSH option ${OPTIONNAME} is unknown (not defined)"
Display --indent 4 --text "- OpenSSH option: ${OPTIONNAME}" --result DEFAULT --color WHITE
Report "unknown_config_option[]=ssh|$SSH_DAEMON_CONFIG}|${OPTIONNAME}|"
else
LogText "Result: Option ${OPTIONNAME} not found in output"
Display --indent 4 --text "- SSH option: ${OPTIONNAME}" --result "${STATUS_NOT_FOUND}" --color WHITE
Display --indent 4 --text "- OpenSSH option: ${OPTIONNAME}" --result "${STATUS_NOT_FOUND}" --color WHITE
fi
else
if IsVerbose; then Display --indent 4 --text "- SSH option: ${OPTIONNAME}" --result "SKIPPED (via config)" --color WHITE; fi
if IsVerbose; then Display --indent 4 --text "- OpenSSH option: ${OPTIONNAME}" --result "SKIPPED (via config)" --color WHITE; fi
fi
done
fi
@ -290,32 +294,32 @@
#################################################################################
#
# Test : SSH-7440
# Description : AllowUsers / AllowGroups
# Description : OpenSSH - AllowUsers / AllowGroups
# Goal : Check if only a specific amount of users/groups can log in to the system
if [ ${SSH_DAEMON_RUNNING} -eq 1 -a ! -z "${SSH_DAEMON_OPTIONS_FILE}" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no SSH-7440 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check SSH option: AllowUsers and AllowGroups"
if [ ${OPENSSHD_RUNNING} -eq 1 -a ! -z "${SSH_DAEMON_OPTIONS_FILE}" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no SSH-7440 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check OpenSSH option: AllowUsers and AllowGroups"
if [ ${SKIPTEST} -eq 0 ]; then
FOUND=0
# AllowUsers
FIND=$(${EGREPBINARY} -i "^AllowUsers" ${SSH_DAEMON_OPTIONS_FILE} | ${AWKBINARY} '{ print $2 }')
if [ ! -z "${FIND}" ]; then
LogText "Result: AllowUsers set, with value ${FIND}"
Display --indent 4 --text "- SSH option: AllowUsers" --result "${STATUS_FOUND}" --color GREEN
Display --indent 4 --text "- OpenSSH option: AllowUsers" --result "${STATUS_FOUND}" --color GREEN
FOUND=1
else
LogText "Result: AllowUsers is not set"
Display --indent 4 --text "- SSH option: AllowUsers" --result "${STATUS_NOT_FOUND}" --color WHITE
Display --indent 4 --text "- OpenSSH option: AllowUsers" --result "${STATUS_NOT_FOUND}" --color WHITE
fi
# AllowGroups
FIND=$(${EGREPBINARY} -i "^AllowGroups" ${SSH_DAEMON_OPTIONS_FILE} | ${AWKBINARY} '{ print $2 }')
if [ ! -z "${FIND}" ]; then
LogText "Result: AllowUsers set ${FIND}"
Display --indent 4 --text "- SSH option: AllowGroups" --result "${STATUS_FOUND}" --color GREEN
Display --indent 4 --text "- OpenSSH option: AllowGroups" --result "${STATUS_FOUND}" --color GREEN
FOUND=1
else
LogText "Result: AllowGroups is not set"
Display --indent 4 --text "- SSH option: AllowGroups" --result "${STATUS_NOT_FOUND}" --color WHITE
Display --indent 4 --text "- OpenSSH option: AllowGroups" --result "${STATUS_NOT_FOUND}" --color WHITE
fi
if [ ${FOUND} -eq 1 ]; then
@ -331,6 +335,7 @@
#
Report "ssh_daemon_running=${SSH_DAEMON_RUNNING}"
Report "openssh_daemon_running=${OPENSSHD_RUNNING}"
WaitForKeyPress

View File

@ -251,8 +251,7 @@
Register --test-no HTTP-6640 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Determining existence of specific Apache modules"
if [ ${SKIPTEST} -eq 0 ]; then
# Check modules, module
CheckItem "apache_module" "/mod_evasive([0-9][0-9])?.so"
if [ ${ITEM_FOUND} -eq 1 ]; then
if CheckItem "apache_module" "/mod_evasive([0-9][0-9])?.so"; then
Display --indent 10 --text "mod_evasive: anti-DoS/brute force" --result "${STATUS_FOUND}" --color GREEN
AddHP 3 3
else
@ -271,8 +270,7 @@
Register --test-no HTTP-6641 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Determining existence of specific Apache modules"
if [ ${SKIPTEST} -eq 0 ]; then
# Check modules, module
CheckItem "apache_module" "/mod_(reqtimeout|qos).so"
if [ ${ITEM_FOUND} -eq 1 ]; then
if CheckItem "apache_module" "/mod_(reqtimeout|qos).so"; then
Display --indent 10 --text "mod_reqtimeout/mod_qos" --result "${STATUS_FOUND}" --color GREEN
AddHP 3 3
else
@ -290,8 +288,7 @@
Register --test-no HTTP-6643 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Determining existence of specific Apache modules"
if [ ${SKIPTEST} -eq 0 ]; then
# Check modules, module
CheckItem "apache_module" "/mod_security2.so"
if [ ${ITEM_FOUND} -eq 1 ]; then
if CheckItem "apache_module" "/mod_security2.so"; then
Display --indent 10 --text "ModSecurity: web application firewall" --result "${STATUS_FOUND}" --color GREEN
AddHP 3 3
else

48
lynis
View File

@ -21,6 +21,11 @@
# Lynis is an automated auditing tool for Unix based operating systems.
#
#################################################################################
#
# Code quality: don't allow using undefined variables
set -o nounset
#
#################################################################################
#
# In Solaris /bin/sh is not POSIX, but /usr/xpg4/bin/sh is.
# Switch to /usr/xpg4/bin/sh if it exists and we are not already running it.
@ -35,10 +40,10 @@
PROGRAM_AUTHOR_CONTACT="lynis-dev@cisofy.com"
# Version details
PROGRAM_RELEASE_DATE="2019-03-21"
PROGRAM_RELEASE_TIMESTAMP=1553157295
PROGRAM_RELEASE_TYPE="final" # dev or final
PROGRAM_VERSION="2.7.3"
PROGRAM_RELEASE_DATE="2019-06-29"
PROGRAM_RELEASE_TIMESTAMP=1561383761
PROGRAM_RELEASE_TYPE="dev" # dev or final
PROGRAM_VERSION="3.0.0"
# Source, documentation and license
PROGRAM_SOURCE="https://github.com/CISOfy/lynis"
@ -55,11 +60,6 @@
DISPLAY_LANG="${LANG}" # required by function Display to deal with multi-bytes characters.
# Code quality:
# Set strict checking for development version for first part of code. After
# initialization this is checked with strict profile option.
if [ ${PROGRAM_RELEASE_TYPE} = "dev" ]; then set -u; fi
#
#################################################################################
#
@ -67,6 +67,9 @@
#
#################################################################################
#
# Check setuid bit
if [ -u "$0" ]; then echo "The called binary has the set-user-id bit - As this is unusual, execution will be stopped."; exit 1; fi
# Work directory
WORKDIR=$(pwd)
@ -139,8 +142,7 @@ Make sure to execute ${PROGRAM_NAME} from untarred directory or check your insta
#################################################################################
#
# Perform a basic check for permissions. After including functions, using SafePerms()
WARN_ON_FILE_ISSUES=1
WARN_ON_FILE_ISSUES_ASKED=0
IGNORE_FILE_PERMISSION_ISSUES=0
FILES_TO_CHECK="consts functions"
@ -192,14 +194,10 @@ Make sure to execute ${PROGRAM_NAME} from untarred directory or check your insta
printf "\n Option 2) Change ownership of the related files (or full directory).\n\n Commands (full directory):\n # cd ..\n # chown -R 0:0 lynis\n # cd lynis\n # ./lynis audit system"
fi
printf "\n\n[ Press ENTER to continue, or CTRL+C to cancel ]"
WARN_ON_FILE_ISSUES_ASKED=1
IGNORE_FILE_PERMISSION_ISSUES=1
read DUMMY
fi
if [ ${WARN_ON_FILE_ISSUES_ASKED} -eq 1 ]; then
WARN_ON_FILE_ISSUES=0
fi
# Now include files if permissions are correct, or user decided to continue
. ${INCLUDEDIR}/consts
. ${INCLUDEDIR}/functions
@ -613,6 +611,9 @@ ${NORMAL}
if [ ${EOL} -eq 1 ]; then
echo " End-of-life: ${WARNING}YES${NORMAL}"
ReportWarning "GEN-0010" "This version ${OS_VERSION} is marked end-of-life as of ${EOL_DATE}"
elif [ ${EOL} -eq 255 ]; then
# TODO - mark as item where community can provide help
LogText "Note: the end-of-life of '${OS_FULLNAME}' could not be checked. Entry missing in software-eol.db?"
fi
if [ ! -z "${OS_MODE}" ]; then echo " Operating system mode: ${OS_MODE}"; fi
@ -853,8 +854,17 @@ ${NORMAL}
LogText "Action: checking plugin status in profile: ${PROFILE}"
FIND3=$(grep "^plugin=${FIND2}" ${PROFILE})
if [ ! -z "${FIND3}" ]; then
LogText "Result: plugin enabled in profile (${PROFILE})"
PLUGIN_ENABLED_STATE=1
FOUND=0
for I in ${DISABLED_PLUGINS}; do
if [ "${I}" = "${FIND2}" ]; then
FOUND=1
LogText "Result: plugin ${FIND2} is specifically disabled"
fi
done
if [ ${FOUND} -eq 0 ]; then
LogText "Result: plugin enabled in profile (${PROFILE})"
PLUGIN_ENABLED_STATE=1
fi
fi
done
if [ ${PLUGIN_ENABLED_STATE} -eq 1 ]; then
@ -948,7 +958,7 @@ ${NORMAL}
for INCLUDE_TEST in ${INCLUDE_TESTS}; do
INCLUDE_FILE="${INCLUDEDIR}/tests_${INCLUDE_TEST}"
if [ -f ${INCLUDE_FILE} ]; then
if SafePerms ${INCLUDE_FILE}; then
if SafeFile ${INCLUDE_FILE}; then
. ${INCLUDE_FILE}
else
LogText "Exception: skipping test category ${INCLUDE_TEST}, file ${INCLUDE_FILE} has bad permissions (should be 640, 600 or 400)"