Code Monkey home page Code Monkey logo

cis-benchmarks-audit's Introduction

CIS Benchmarks Audit

Latest version GitHub Actions License CodeFactor Code style: black

This repo provides an unofficial, standalone, zero-install, zero-dependency, Python 3 script which can check your system against published CIS Hardening Benchmarks to offer an indication of your system's preparedness for compliance to the official standard.

How do I use this?

Download:

curl -LO https://raw.githubusercontent.com/finalduty/cis_benchmarks_audit/main/cis_audit.py && chmod 750 cis_audit.py

Run

#usage: cis_audit.py [-h] [--level {1,2}] [--include INCLUDES [INCLUDES ...]]
                    [--exclude EXCLUDES [EXCLUDES ...]]
                    [-l {DEBUG,INFO,WARNING,CRITICAL}] [--debug] [--nice]
                    [--no-nice] [--no-colour]
                    [--system-type {server,workstation}] [--server]
                    [--workstation] [--outformat {csv,json,psv,text,tsv}]
                    [--text] [--json] [--csv] [--psv] [--tsv] [-V] [-c CONFIG]

This script runs tests on the system to check for compliance against the CIS Benchmarks. No changes are made to system files by this script.

optional arguments:
  -h, --help            show this help message and exit
  --level {1,2}         Run tests for the specified level only
  --include INCLUDES [INCLUDES ...]
                        Space delimited list of tests to include
  --exclude EXCLUDES [EXCLUDES ...]
                        Space delimited list of tests to exclude
  -l {DEBUG,INFO,WARNING,CRITICAL}, --log-level {DEBUG,INFO,WARNING,CRITICAL}
                        Set log output level
  --debug               Run script with debug output turned on. Equivalent to --log-level DEBUG
  --nice                Lower the CPU priority for test execution. This is the default behaviour.
  --no-nice             Do not lower CPU priority for test execution. This may make the tests complete faster but at the cost of putting a higher load on the server. Setting this overrides the --nice option.
  --no-colour, --no-color
                        Disable colouring for STDOUT. Output redirected to a file/pipe is never coloured.
  --system-type {server,workstation}
                        Set which test level to reference
  --server              Use "server" levels to determine which tests to run. Equivalent to --system-type server [Default]
  --workstation         Use "workstation" levels to determine which tests to run. Equivalent to --system-type workstation
  --outformat {csv,json,psv,text,tsv}
                        Output type for results
  --text                Output results as text. Equivalent to --output text [default]
  --json                Output results as json. Equivalent to --output json
  --csv                 Output results as comma-separated values. Equivalent to --output csv
  --psv                 Output results as pipe-separated values. Equivalent to --output psv
  --tsv                 Output results as tab-separated values. Equivalent to --output tsv
  -V, --version         Print version and exit
  -c CONFIG, --config CONFIG
                        Location of config file to load

Examples:
    
    Run with debug enabled:
    ./cis_audit.py --debug
        
    Exclude tests from section 1.1 and 1.3.2:
    ./cis_audit.py --exclude 1.1 1.3.2
        
    Include tests only from section 4.1 but exclude tests from section 4.1.1:
    ./cis_audit.py --include 4.1 --exclude 4.1.1
        
    Run only level 1 tests
    ./cis_audit.py --level 1
        
    Run level 1 tests and include some but not all SELinux questions
    ./cis_audit.py --level 1 --include 1.6 --exclude 1.6.1.2

Example Results

# ./cis-audit.sh --include 5.2
[00:00:01] (โœ“) 14 of 14 tests completed 

 CIS CentOS 7 Benchmark v2.2.0 Results 
---------------------------------------
ID      Description                                                Scoring  Level  Result  Duration
--      -----------                                                -------  -----  ------  --------

5       Access Authentication and Authorization
5.2     SSH Server Configuration
5.2.1   Ensure permissions on /etc/ssh/sshd_config are configured  Scored   1      Pass    33ms
5.2.2   Ensure SSH Protocol is set to 2                            Scored   1      Pass    5ms
5.2.3   Ensure SSH LogLevel is set to INFO                         Scored   1      Pass    6ms
5.2.4   Ensure SSH X11 forwarding is disabled                      Scored   1      Pass    4ms
5.2.5   Ensure SSH MaxAuthTries is set to 4 or less                Scored   1      Pass    9ms
5.2.6   Ensure SSH IgnoreRhosts is enabled                         Scored   1      Pass    5ms
5.2.7   Ensure SSH HostbasedAuthentication is disabled             Scored   1      Pass    5ms
5.2.8   Ensure SSH root login is disabled                          Scored   1      Fail    8ms
5.2.9   Ensure SSH PermitEmptyPasswords is disabled                Scored   1      Pass    5ms
5.2.10  Ensure SSH PermitUserEnvironment is disabled               Scored   1      Pass    8ms
5.2.11  Ensure only approved ciphers are used                      Scored   1      Pass    16ms
5.2.12  Ensure only approved MAC algorithms are used               Scored   1      Pass    45ms
5.2.13  Ensure SSH Idle Timeout Interval is configured             Scored   1      Fail    15ms
5.2.14  Ensure SSH LoginGraceTime is set to one minute or less     Scored   1      Pass    11ms
5.2.15  Ensure SSH access is limited                               Skipped  1              
5.2.16  Ensure SSH warning banner is configured                    Scored   1      Pass    6ms

Passed 13 of 15 tests in 1 seconds (1 Skipped, 0 Errors)

Supported Versions

OS Benchmark Versions Python Version
CentOS 7 3.1.2 3.6

Caveats

Terms of Use

Use of the CIS Benchmarks are subject to the Terms of Use for Non-Member CIS Products

CentOS 7 & Python 3

Whilst this repo intends to follow a zero dependency approach, it is not practical to support Python 2.7, which is what is installed by default on CentOS 7. You can however easily install Python 3.6 via yum, which I hope is ok for your environment:

$ sudo yum install python3 -y

Disclaimer

This is not a replacement for a full audit and a passing result from this script does not necessarily mean that you are compliant (but it should give you a good idea of where to start).

No warranty is offered and no responsibility will be taken for damage to systems resulting from the use of this tool.

License

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

CC BY-NC-SA 4.0

cis-benchmarks-audit's People

Contributors

finalduty avatar nandac avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cis-benchmarks-audit's Issues

5.1.8 if in my system doesn't turn SELinux

If i did not turn on the SELinux, the permission setting will not contain the '.' after the permission?

[ $(ls -l /etc/at.allow 2>/dev/null | awk '{ print $1" "$3" "$4 }' | grep -c -- "-rw-------. root root") -eq 1 ]

e.g.
-rw------- No SELinux enabled / attribute is set
-rw-------.

Several of the tests produce false failures

1.2.1 - is too restrictive since it assumes the existence of specific repo names (base and updates).

1.7.1.4 - if /etc/motd is a symbolic link then test_perms incorrectly inspects link perms instead of file.

3.6.3 and 3.6.4 - this doesn't take into account the iptables rules potentially having comments in them.

4.2.1.3 - doesn't find FileCreateMode if it is set under a /etc/rsyslog.d/*.conf file.

5.4.4 - doesn't find user mask if it occurs multiple times in file like in an if/else condition.

v0.20 - Refactor to Python

Overview

Reviewing this repo after a few years has found that while it is popular, I have not kept up with development of it as much as I would like.

After review, the projects goal to provide an easy to use single-file executable with zero external requirements remains intact but it is becoming increasingly obvious that using bash is not the most effective language going forward.

The repository health shows some concerning symptoms that make me think this contribution is not as good as it should be. Notably, the age of issues is very high and the ratio of forks to pull requests suggest that the community find it easier to adapt/fix things themselves than push back to this repo. This leads to a dilution of community efforts, duplication of efforts and reduction in potential benefits gained by using this repo.

Problem/Issues

  1. A lot (most) of the issues raised relate to individual tests having problems that are difficult to test/capture. Additionally there is currently no way of easily detecting/preventing regressions.
  2. Community contribution experience is poor. Issues remain open and PRs unaddressed for long periods of time
  3. Ability to support different / future versions of the benchmarks is difficult with the current structure

Solutions

  1. Implement testing suite and automated testing

    • Implement unit tests using Pytest
    • Implement GitHub Actions to run test suites
  2. Contribution experience
    Many of the issues that have remained open are due to difficulty in fixing/replicating/preventing-regression. Automated regression testing as above will help, but there is still a process improvement to be made. This may need to be split to a different issue.

  3. Improve support for various benchmarks/os/python versions

    • Rename test functions to be more descriptive / not tied to a specific benchmark version, e.g. test_1.1.1.x -> test_kernel_module_is_disabled
    • Add ability to support multiple benchmark versions
    • Add ability to support multiple OS/Python versions with tox

Supercedes #28

Update to CentOS 7 v3.0.0 standard

Overview

CIS released v3.0.0 of the CentOS 7 hardening benchmark on 2020-06-30.

This release involves a major rewrite of the framework and tests which will break compatibility with previous versions.

To Do's

  • Rename test functions
  • Implement unit tests using Shellspec
  • Ensure conformance with Shellcheck
  • No longer allow test functions to define their own description
  • Rewrite test functions to explicitly produce a Pass or Fail result

Future Considerations

  • Framework should make improvements to prepare for supporting different operating systems.
  • Framework will need to support CentOS 8 v1.0.0 (#29)
  • Framework should support Debian/Ubuntu

Details

Rename test functions

v3.0.0 changed the ordering of some tests. As such, it no longer makes sense to name test functions after their benchmark id and this change will involve renaming the test functions to a name that more closely matches what they test.

For example:

v0.10 v0.11
test_1.1.1.x test_kernel_module_is_disabled
test_1.2.2 test_gpg_keys_are_configured

The aim is to increase verbosity, which will make test names more descriptive and allow renumbering / reordering of tests in future to be a lot easier. It also means that other Standards such as CentOS 8 or Debian do not have contradictory IDs and test names.

Implement unit tests using Shellspec

Shellspec is a unit testing framework which allows for the creation of testing the functions and mocking files.

This will help improve code quality by offering a greater ability to test different system configurations to ensure that the correct results are returned by the tests.

Full disclosure, I've not used this before, but it looks really promising for helping create a quality tool.

Ensure conformance with Shellcheck

Should be fairly self explanatory. This is a static analysis tool which helps implement better code quality.

No longer allow test functions to define their own description

Previously test functions were (semi-)duplicated in situations where the test was largely the same but the description did not fit the test function design.

This change will allow fewer duplicated test functions (DRY), and help pave the way to support additional OSs in future.

Rewrite test functions to explicitly produce a Pass or Fail result

Previously, the results of test functions would take a default Fail result from a global variable. This worked well to prevent having to specify 'result = "Fail"' in each function, however it made it more difficult to interpret for anyone not familiar with the code, including myself when I haven't touched it in a while.

The aim here is to make each test wholly self-contained, so that contributors can look at a single function and understand all of it in one go. This also is a partial requirement for integrating Shellspec tests effectively.

1.1.17 looks for an extra comma in the check that isn't always there

On one system I had a pass but on another a fail, both matched the CIS check but the script includes an extra comma match there is not always present.

mount | grep /dev/shm
PASS RESULT = tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,seclabel)
FAIL RESULT = tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,noexec)

test 1.5.1 fails if entry is in multiple files

test 1.5.1 fails if the configuration is listed on multiple files

grep "fs.suid_dumpable" /etc/sysctl.conf /etc/sysctl.d/*.conf

/etc/sysctl.conf:fs.suid_dumpable = 0
/etc/sysctl.d/99-sysctl.conf:fs.suid_dumpable = 0

the next comparison will fail, as there are multiple lines output being compared.
sed 's/^.*://')" == "fs.suid_dumpable = 0"

maybe add a pipe to uniq to resolve this?

[ "$(grep "fs.suid_dumpable" /etc/sysctl.conf /etc/sysctl.d/.conf | sed 's/^.://' | uniq)" == "fs.suid_dumpable = 0" ]

Password requirements 5.3.1 fails due to syntax

Tabs in the /etc/pam.d/password-auth and /etc/pam.d/system-auth are not configured right so the formatting can cause a failure. Also the /etc/security/pwquality.conf requires spaces between the equals characters but the check doesn't expect the spaces so it fails here also.

Update deprecated NodeJS GitHub Actions

Node.js 12 actions are deprecated. For more information see: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/. Please update the following actions to use Node.js 16: actions/checkout, actions/setup-python, codecov/codecov-action, actions/setup-python, actions/checkout

Screen Shot 2022-10-13 at 12 26 09

The CI Tests workflow https://github.com/finalduty/cis-benchmarks-audit/blob/devel/.github/workflows/ci-tests.yaml needs to be updated with the latest actions

Ensure mail transfer agent test 2.2.15 failes regardless of status

The grep catches any occurrence of :25 including those inside a MAC address. This causes a false 'fail' status.

Adding a proceeding space avoids catching the possible MAC address result and it should only find the port number..

## Tests Start ##
        [ $(netstat -tupln | egrep -v '127.0.0.1|::1:' | grep ":25 " | wc -l) -eq 0 ] && result="Pass"
## Tests End ##

Email or report output?

Can you suggest a way to put the test in to a cron job with an email output, or perhaps just output the final report to file so it can be wrapped in another script to then send as an email attachment.

Certain kernel disabled test failing based on incorrect string search

line 1108 in /main/cis_audit.py
if r.stdout[0] == 'install /bin/true\n':

Tests were failing, but I could verify they shouldn't be through manual means.

Here is CMD output printed from within the script test result.

'install /bin/true '

My output has a single space, not a new line.

Changing the expected string \n to a single space in the above file/line has resolved this issue for me.

No module named 'tests'

[root@RED-HAT-8]# ./cis_audit.py --level 2
Traceback (most recent call last):
  File "./cis_audit.py", line 39, in <module>
    from tests.integration import (
ModuleNotFoundError: No module named 'tests'

Test 2.2.2 will always pass

In test 2.2.2 below it looks like the test will ALWAYS pass with return 0 since all output and errors are wiped out before piping to wc -l

[ $(rpm -qa xorg-x11* &>/dev/null | wc -l) -eq 0 ] && result="Pass"

Support for Centos 9/Amazon Linux 2023

@finalduty Is there any chance that Centos 9 or Amazon Linux 2023 hosts will be supported in the future?

I know this would be quite an ask but the benchmarking script works great for Amazon Linux 2 and just wanted to check if something was on the cards.

Cheers

No result in this test?

Hi there,
I really appreciate your work, I'm working on matching this code for RHEL 7 (CIS benchmark v3.0.0)
and I am doing some changes in the code.
I was looking on test test_3.x-single and I saw that not all the conditional statement return the "result" output,
you can see that the second conditional (grep test) returning the state but not the result, is it OK?
(line https://github.com/finalduty/cis_benchmarks_audit/blob/1d134f465baf9fcff1939cbb9e798155a0c0e182/cis-audit.sh#L1212)

test_3.x-single() {
id=$1
level=$2
protocol=$3
sysctl=$4
val=$5
description=$( echo $@ | awk '{$1=$2=$3=$4=$5=""; print $0}' | sed 's/^ //')
scored="Scored"
test_start_time="$(test_start $id)"
[ "$(sysctl net.$protocol.$sysctl)" == "net.$protocol.$sysctl = $val" ] && result="Pass"
[ "$(grep "net.$protocol.$sysctl" /etc/sysctl.conf /etc/sysctl.d/
.conf | sed -e 's/^.*://' -e 's/\s//g' | uniq)" == "net.$protocol.$sysctl=$val" ] || state=1
duration="$(test_finish $id $test_start_time)ms"
write_result "$id,$description,$scored,$level,$result,$duration"
}

Bootloader password test 1.4.2 fails regardless of status

The grep doesn't account for the indented lines (leading spaces) and fails. The check should also confirm that the users.cfg contains the password.

I suggest..

## Tests Start ##
    state=0

    [ $(grep "set superusers" /boot/grub2/grub.cfg | wc -l) -eq 0 ] && state=1
    [ $(grep "password_pbkdf2" /boot/grub2/grub.cfg | wc -l ) -eq 0 ] && state=1
    [ $(grep "^GRUB2_PASSWORD" /boot/grub2/user.cfg | wc -l ) -eq 0 ] && state=1
    [ $state -eq 0 ] && result="Pass"
## Tests End ##

Is test 6.2.6 Ensure no duplicate group names exist implemented?

@finalduty I would like to take this opportunity to thank you for developing this audit script.

My question is in regards to test 6.2.6 Ensure no duplicate group names exist which does not seem to be implemented as it points to the same function as test 6.2.5 Ensure no duplicate user names exist.

According to the CIS document, this can be implemented in Bash as follows:

#!/bin/bash
cut -d: -f1 /etc/group | sort | uniq -d | while read -r x; do echo "Duplicate group name ${x} in /etc/group"
done

The following Python code should do the trick although it is untested:

def audit_duplicate_group_names(self) -> int:
    state = 0
    cmd = R"cut -d: -f1 /etc/group | sort | uniq -d"

    r = self._shellexec(cmd)
    if r.stdout[0] != "":
        state = 1

    return state

Kindly let me know if this test has been implemented or not.

Many thanks.

4.1.18 fails whilst configuration is in place

I'm not sure if this is a bug or a problem with my specific system but check 4.1.18 fails because the "auditctl -l | tail -l"' does not bring back the "-e 2". The check advised in the CIS benchmark is "grep "^\s*[^#]" /etc/audit/audit.rules | tail -1". My system does pass on this check.

Doesn't behave well if files are missing.

Doesn't behave well if files are missing.

Example:
[00:00:06] (|) 102 of 106 tests completed ls: cannot access '/etc/hosts.allow': No such file or directory
./cis-audit.sh: line 1323: [: ==: unary operator expected
./cis-audit.sh: line 1324: [: ==: unary operator expected
./cis-audit.sh: line 1325: [: ==: unary operator expected

Various audit checks incorrect

Various checks in the audit rules (4) are not correct when compared to to the CIS benchmarking recommendations. These cause failures when in fact the correct settings are in place. Some things that are not checked or incorrectly checked in the /etc/audit/audit.rules file are:

4.1.6
MISSING: -w /etc/sysconfig/network-scripts/ -p wa -k system-locale
4.1.7
MISSING: -w /usr/share/selinux/ -p wa -k MAC-policy
4.1.8
this check filtered on the word 'logins' which also exists in 4.1.9 and causes a false failure
4.1.9
this check is filtered on 'session' but two the last two rules should be 'logins' (as below), this is the cause for the failure above but also renders this check invalid.
-w /var/log/wtmp -p wa -k logins
-w /var/log/btmp -p wa -k logins
4.1.14
this check is filtered on 'delete' which also exists in a comments line that is part of the default config. 4.1.17 also has the word delete and both causes a false failure.
4.1.15
missing a trailing forward slash on the folder name, should be
-w /etc/sudoers.d/ -p wa -k scope'
4.1.17
this check is filtered on 'time-change' which must be a typo from a copy\paste, its also missing a -F on the rule, should be.
search_term="modules"
expected='-w /sbin/insmod -p x -k modules\n
-w /sbin/rmmod -p x -k modules\n
-w /sbin/modprobe -p x -k modules\n
-a always,exit -F arch=b64 -S init_module -S delete_module -k modules'

Not found 'Score' result

I have an issue with the result. When I execute to audit server, my result does not show the 'Score' values as in your example.

image

5.3.3 fails when multiple entries exist

Whilst the CIS benchmark check doesn't include it I suggest the check also matches on the word 'remember' in the first step. This avoids a failure when there are multiple entries in the files.

    pwauth_history=$(egrep '^password\s+required\s+pam_pwhistory.so\s+remember' /etc/pam.d/password-auth)
    sysauth_history=$(egrep '^password\s+required\s+pam_pwhistory.so\s+remember' /etc/pam.d/system-auth)
    pwauth_unix=$(egrep '^password\s+sufficient\s+pam_unix.so\s+remember' /etc/pam.d/password-auth)
    sysauth_unix=$(egrep '^password\s+sufficient\s+pam_unix.so\s+remember' /etc/pam.d/system-auth)

5.6 should be egrep and syntax change

As noted on bug #6 this check fails due to the spacing and requires a change to egrep with a slightly different syntax...

egrep "^auth\s+required\s+pam_wheel.so\s+use_uid" /etc/pam.d/su

test_is_installed fails regardless of status

The rpm test always returns one line so the current match for -eq 0 means its always a fail regardless of the actual state.

I suggest it includes a grep for "not installed" with -eq 1...

Tests Start

[ $(rpm -q ntp | grep "not installed" &>/dev/null; echo $?) -eq 1 ] && result="Pass"

Tests End

5.4.1.4 check returns date rather than integer

The command chage --list {user} returns a date which is the date when the account would be locked due to inactivity. The check is expecting an integer that is the number of days as with the prior /etc/login.defs check but this will not work.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.