diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/ansible/rhel9.yml b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/ansible/rhel9.yml new file mode 100644 index 000000000000..cb4e2c447f6f --- /dev/null +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/ansible/rhel9.yml @@ -0,0 +1,55 @@ +# platform = Red Hat Enterprise Linux 9 +# reboot = false +# strategy = restrict +# complexity = low +# disruption = low + +{{% set rx_beg = "^[\s]*-a[\s]+always,exit[\s]+" %}} +{{% set rx_b32 = "-F[\s]+arch=b32[\s]+" %}} +{{% set rx_b64 = "-F[\s]+arch=b64[\s]+" %}} +{{% set rx_path = "-F[\s]+path=" ~ xccdf_value("var_accounts_passwords_pam_faillock_dir") ~ "[\s]+" %}} +{{% set rx_perm = "-F[\s]+perm=wa[\s]+" %}} +{{% set rx_auid = "-F[\s]+auid>=" ~ uid_min ~ "[\s]+-F[\s]+auid!=unset[\s]+" %}} +{{% set rx_end = "(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$" %}} + +{{{ ansible_instantiate_variables("var_accounts_passwords_pam_faillock_dir") }}} + +- name: "{{{ rule_title }}} - Service facts" + ansible.builtin.service_facts: + +- name: "{{{ rule_title }}} - Set faillock_audit_rules fact" + ansible.builtin.set_fact: + faillock_audit_rules: + - rule: '-a always,exit -F arch=b32 -F path={{ var_accounts_passwords_pam_faillock_dir }} -F perm=wa -F auid>={{{ uid_min }}} -F auid!=unset -k logins' + regex: {{{ rx_beg + rx_b32 + rx_path + rx_perm + rx_auid + rx_end }}} + - rule: '-a always,exit -F arch=b64 -F path={{ var_accounts_passwords_pam_faillock_dir }} -F perm=wa -F auid>={{{ uid_min }}} -F auid!=unset -k logins' + regex: {{{ rx_beg + rx_b64 + rx_path + rx_perm + rx_auid + rx_end }}} + +- name: "{{{ rule_title }}} - Update /etc/audit/rules.d/logins.rules to audit faillock" + ansible.builtin.lineinfile: + path: /etc/audit/rules.d/logins.rules + line: "{{ item.rule }}" + regexp: "{{ item.regex }}" + create: yes + mode: 0600 + when: + - '"auditd.service" in ansible_facts.services' + register: augenrules_faillock_update_result + with_items: "{{ faillock_audit_rules }}" + +- name: "{{{ rule_title }}} - Update /etc/audit/audit.rules to audit faillock" + ansible.builtin.lineinfile: + path: /etc/audit/audit.rules + line: "{{ item.rule }}" + regexp: "{{ item.regex }}" + create: yes + mode: 0600 + when: + - '"auditd.service" in ansible_facts.services' + register: auditctl_faillock_update_result + with_items: "{{ faillock_audit_rules }}" + +- name: "{{{ rule_title }}} - Restart auditd" + ansible.builtin.command: /usr/sbin/service auditd restart + when: + - augenrules_faillock_update_result is changed or auditctl_faillock_update_result is changed diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/bash/rhel9.sh b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/bash/rhel9.sh new file mode 100644 index 000000000000..4c5a10628337 --- /dev/null +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/bash/rhel9.sh @@ -0,0 +1,18 @@ +# platform = Red Hat Enterprise Linux 9 + +{{{ bash_instantiate_variables("var_accounts_passwords_pam_faillock_dir") }}} + +[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64") + +for ARCH in "${RULE_ARCHS[@]}" +do + ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH" + OTHER_FILTERS="-F path=${var_accounts_passwords_pam_faillock_dir} -F perm=wa" + AUID_FILTERS="-F auid>={{{ uid_min }}} -F auid!=unset" + SYSCALL="" + SYSCALL_GROUPING="" + KEY="logins" + + {{{ bash_fix_audit_syscall_rule("augenrules", "$ACTION_ARCH_FILTERS", "$OTHER_FILTERS", "$AUID_FILTERS", "$SYSCALL", "$SYSCALL_GROUPING", "$KEY") }}} + {{{ bash_fix_audit_syscall_rule("auditctl", "$ACTION_ARCH_FILTERS", "$OTHER_FILTERS", "$AUID_FILTERS", "$SYSCALL", "$SYSCALL_GROUPING", "$KEY") }}} +done diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/oval/rhel9.xml b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/oval/rhel9.xml new file mode 100644 index 000000000000..194b281a15e6 --- /dev/null +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/oval/rhel9.xml @@ -0,0 +1,88 @@ + + + {{{ oval_metadata("Record Attempts to Alter Logon and Logout Events - faillock", rule_title=rule_title) }}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ^/etc/audit/rules\.d/.*\.rules$ + + 1 + + + + + + ^/etc/audit/rules\.d/.*\.rules$ + + 1 + + + + + + /etc/audit/audit.rules + + 1 + + + + + + /etc/audit/audit.rules + + 1 + + + + + ^\-a\s+always,exit\s+\-F\s+arch=b32\s+\-F\s+path= + + + + \s+\-F\s+perm=\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b.*$ + + + + + + + ^\-a\s+always,exit\s+\-F\s+arch=b64\s+\-F\s+path= + + + + \s+\-F\s+perm=\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b.*$ + + + + + + + + diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/rule.yml b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/rule.yml index 7681a2a4b9d1..1e58e0672bf3 100644 --- a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/rule.yml +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/rule.yml @@ -45,6 +45,16 @@ ocil_clause: 'the command does not return a line, or the line is commented out' ocil: |- {{{ ocil_audit_rules_watch(xccdf_value("var_accounts_passwords_pam_faillock_dir"), "logins") }}} +{{% if product in ["rhel9"] %}} +warnings: + - general: |- + Note that the OVAL check for this rule accepts audit rules with or without + the auid filters (-F auid>=1000 -F auid!=unset). + However, the Bash and Ansible remediations will add these filters to ensure + full compliance. This approach ensures compatibility with existing systems + while bringing them into compliance when remediation is applied. +{{% endif %}} + template: name: audit_rules_watch vars: diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/tests/rhel9_correct_auid.pass.sh b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/tests/rhel9_correct_auid.pass.sh new file mode 100644 index 000000000000..7e2f8ee1f8e8 --- /dev/null +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/tests/rhel9_correct_auid.pass.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# platform = Red Hat Enterprise Linux 9 +# packages = audit +# variables = var_accounts_passwords_pam_faillock_dir=/var/log/faillock + +echo "-a always,exit -F arch=b32 -F path=/var/log/faillock -F perm=wa -F auid>=1000 -F auid!=unset -F key=logins" >> /etc/audit/rules.d/logins.rules +echo "-a always,exit -F arch=b64 -F path=/var/log/faillock -F perm=wa -F auid>=1000 -F auid!=unset -F key=logins" >> /etc/audit/rules.d/logins.rules diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/tests/rhel9_missing_auid.fail.sh b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/tests/rhel9_missing_auid.fail.sh new file mode 100644 index 000000000000..8d9f0558b0ea --- /dev/null +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/tests/rhel9_missing_auid.fail.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# platform = Red Hat Enterprise Linux 9 +# packages = audit +# variables = var_accounts_passwords_pam_faillock_dir=/var/log/faillock + +# This test should fail because it's missing the auid filters +echo "-a always,exit -F arch=b32 -F path=/var/log/faillock -F perm=wa -F key=logins" >> /etc/audit/rules.d/logins.rules +echo "-a always,exit -F arch=b64 -F path=/var/log/faillock -F perm=wa -F key=logins" >> /etc/audit/rules.d/logins.rules diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/tests/rhel9_missing_b32.fail.sh b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/tests/rhel9_missing_b32.fail.sh new file mode 100644 index 000000000000..3ae7b00ea4da --- /dev/null +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_faillock/tests/rhel9_missing_b32.fail.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# platform = Red Hat Enterprise Linux 9 +# packages = audit +# variables = var_accounts_passwords_pam_faillock_dir=/var/log/faillock + +# This test should fail because it's missing the b32 arch rule +echo "-a always,exit -F arch=b64 -F path=/var/log/faillock -F perm=wa -F auid>=1000 -F auid!=unset -F key=logins" >> /etc/audit/rules.d/logins.rules diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/ansible/rhel9.yml b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/ansible/rhel9.yml new file mode 100644 index 000000000000..03d5d328706e --- /dev/null +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/ansible/rhel9.yml @@ -0,0 +1,53 @@ +# platform = Red Hat Enterprise Linux 9 +# reboot = false +# strategy = restrict +# complexity = low +# disruption = low + +{{% set rx_beg = "^[\s]*-a[\s]+always,exit[\s]+" %}} +{{% set rx_b32 = "-F[\s]+arch=b32[\s]+" %}} +{{% set rx_b64 = "-F[\s]+arch=b64[\s]+" %}} +{{% set rx_path = "-F[\s]+path=/var/log/lastlog[\s]+" %}} +{{% set rx_perm = "-F[\s]+perm=wa[\s]+" %}} +{{% set rx_auid = "-F[\s]+auid>=" ~ uid_min ~ "[\s]+-F[\s]+auid!=unset[\s]+" %}} +{{% set rx_end = "(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$" %}} + +- name: "{{{ rule_title }}} - Service facts" + ansible.builtin.service_facts: + +- name: "{{{ rule_title }}} - Set lastlog_audit_rules fact" + ansible.builtin.set_fact: + lastlog_audit_rules: + - rule: '-a always,exit -F arch=b32 -F path=/var/log/lastlog -F perm=wa -F auid>={{{ uid_min }}} -F auid!=unset -k logins' + regex: {{{ rx_beg + rx_b32 + rx_path + rx_perm + rx_auid + rx_end }}} + - rule: '-a always,exit -F arch=b64 -F path=/var/log/lastlog -F perm=wa -F auid>={{{ uid_min }}} -F auid!=unset -k logins' + regex: {{{ rx_beg + rx_b64 + rx_path + rx_perm + rx_auid + rx_end }}} + +- name: "{{{ rule_title }}} - Update /etc/audit/rules.d/logins.rules to audit lastlog" + ansible.builtin.lineinfile: + path: /etc/audit/rules.d/logins.rules + line: "{{ item.rule }}" + regexp: "{{ item.regex }}" + create: yes + mode: 0600 + when: + - '"auditd.service" in ansible_facts.services' + register: augenrules_lastlog_update_result + with_items: "{{ lastlog_audit_rules }}" + +- name: "{{{ rule_title }}} - Update /etc/audit/audit.rules to audit lastlog" + ansible.builtin.lineinfile: + path: /etc/audit/audit.rules + line: "{{ item.rule }}" + regexp: "{{ item.regex }}" + create: yes + mode: 0600 + when: + - '"auditd.service" in ansible_facts.services' + register: auditctl_lastlog_update_result + with_items: "{{ lastlog_audit_rules }}" + +- name: "{{{ rule_title }}} - Restart auditd" + ansible.builtin.command: /usr/sbin/service auditd restart + when: + - augenrules_lastlog_update_result is changed or auditctl_lastlog_update_result is changed diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/bash/rhel9.sh b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/bash/rhel9.sh new file mode 100644 index 000000000000..6f21664f964a --- /dev/null +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/bash/rhel9.sh @@ -0,0 +1,16 @@ +# platform = Red Hat Enterprise Linux 9 + +[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64") + +for ARCH in "${RULE_ARCHS[@]}" +do + ACTION_ARCH_FILTERS="-a always,exit -F arch=$ARCH" + OTHER_FILTERS="-F path=/var/log/lastlog -F perm=wa" + AUID_FILTERS="-F auid>={{{ uid_min }}} -F auid!=unset" + SYSCALL="" + SYSCALL_GROUPING="" + KEY="logins" + + {{{ bash_fix_audit_syscall_rule("augenrules", "$ACTION_ARCH_FILTERS", "$OTHER_FILTERS", "$AUID_FILTERS", "$SYSCALL", "$SYSCALL_GROUPING", "$KEY") }}} + {{{ bash_fix_audit_syscall_rule("auditctl", "$ACTION_ARCH_FILTERS", "$OTHER_FILTERS", "$AUID_FILTERS", "$SYSCALL", "$SYSCALL_GROUPING", "$KEY") }}} +done diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/oval/rhel9.xml b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/oval/rhel9.xml new file mode 100644 index 000000000000..dbd90ef35635 --- /dev/null +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/oval/rhel9.xml @@ -0,0 +1,86 @@ + + + {{{ oval_metadata("Record Attempts to Alter Logon and Logout Events - lastlog", rule_title=rule_title) }}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ^/etc/audit/rules\.d/.*\.rules$ + + 1 + + + + + + ^/etc/audit/rules\.d/.*\.rules$ + + 1 + + + + + + /etc/audit/audit.rules + + 1 + + + + + + /etc/audit/audit.rules + + 1 + + + + + ^\-a\s+always,exit\s+\-F\s+arch=b32\s+\-F\s+path= + + \/var\/log\/lastlog + + \s+\-F\s+perm=\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b.*$ + + + + + + + ^\-a\s+always,exit\s+\-F\s+arch=b64\s+\-F\s+path= + + \/var\/log\/lastlog + + \s+\-F\s+perm=\b([rx]*w[rx]*a[rx]*|[rx]*a[rx]*w[rx]*)\b.*$ + + + + + + diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/rule.yml b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/rule.yml index 2e1a28d286a8..0953c2db595a 100644 --- a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/rule.yml +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/rule.yml @@ -48,6 +48,16 @@ ocil_clause: 'the command does not return a line, or the line is commented out' ocil: |- {{{ ocil_audit_rules_watch("/var/log/lastlog", "logins") }}} +{{% if product in ["rhel9"] %}} +warnings: + - general: |- + Note that the OVAL check for this rule accepts audit rules with or without + the auid filters (-F auid>=1000 -F auid!=unset). + However, the Bash and Ansible remediations will add these filters to ensure + full compliance. This approach ensures compatibility with existing systems + while bringing them into compliance when remediation is applied. +{{% endif %}} + template: name: audit_rules_watch vars: diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/tests/rhel9_correct_auid.pass.sh b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/tests/rhel9_correct_auid.pass.sh new file mode 100644 index 000000000000..b07974f6db03 --- /dev/null +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/tests/rhel9_correct_auid.pass.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# platform = Red Hat Enterprise Linux 9 +# packages = audit + +echo "-a always,exit -F arch=b32 -F path=/var/log/lastlog -F perm=wa -F auid>=1000 -F auid!=unset -k logins" >> /etc/audit/rules.d/logins.rules +echo "-a always,exit -F arch=b64 -F path=/var/log/lastlog -F perm=wa -F auid>=1000 -F auid!=unset -k logins" >> /etc/audit/rules.d/logins.rules diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/tests/rhel9_missing_auid.fail.sh b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/tests/rhel9_missing_auid.fail.sh new file mode 100644 index 000000000000..109c0a1b21e6 --- /dev/null +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/tests/rhel9_missing_auid.fail.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# platform = Red Hat Enterprise Linux 9 +# packages = audit + +# This test should fail because it's missing the auid filters +echo "-a always,exit -F arch=b32 -F path=/var/log/lastlog -F perm=wa -k logins" >> /etc/audit/rules.d/logins.rules +echo "-a always,exit -F arch=b64 -F path=/var/log/lastlog -F perm=wa -k logins" >> /etc/audit/rules.d/logins.rules diff --git a/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/tests/rhel9_missing_b32.fail.sh b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/tests/rhel9_missing_b32.fail.sh new file mode 100644 index 000000000000..53eb866bacd3 --- /dev/null +++ b/linux_os/guide/auditing/auditd_configure_rules/audit_login_events/audit_rules_login_events_lastlog/tests/rhel9_missing_b32.fail.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# platform = Red Hat Enterprise Linux 9 +# packages = audit + +# This test should fail because it's missing the b32 arch rule +echo "-a always,exit -F arch=b64 -F path=/var/log/lastlog -F perm=wa -F auid>=1000 -F auid!=unset -k logins" >> /etc/audit/rules.d/logins.rules