Guide to the Secure Configuration of Ubuntu 20.04

with profile Canonical Ubuntu 20.04 LTS Security Technical Implementation Guide (STIG) V1R12
This Security Technical Implementation Guide is published as a tool to improve the security of Department of Defense (DoD) information systems. The requirements are derived from the National Institute of Standards and Technology (NIST) 800-53 and related documents.
This guide presents a catalog of security-relevant configuration settings for Ubuntu 20.04. It is a rendering of content structured in the eXtensible Configuration Checklist Description Format (XCCDF) in order to support security automation. The SCAP content is is available in the scap-security-guide package which is developed at https://www.open-scap.org/security-policies/scap-security-guide.

Providing system administrators with such guidance informs them how to securely configure systems under their control in a variety of network roles. Policy makers and baseline creators can use this catalog of settings, with its associated references to higher-level security control catalogs, in order to assist them in security baseline creation. This guide is a catalog, not a checklist, and satisfaction of every item is not likely to be possible or sensible in many operational scenarios. However, the XCCDF format enables granular selection and adjustment of settings, and their association with OVAL and OCIL content provides an automated checking capability. Transformations of this document, and its associated automated checking content, are capable of providing baselines that meet a diverse set of policy objectives. Some example XCCDF Profiles, which are selections of items that form checklists and can be used as baselines, are available with this guide. They can be processed, in an automated fashion, with tools that support the Security Content Automation Protocol (SCAP). The DISA STIG, which provides required settings for US Department of Defense systems, is one example of a baseline created from this guidance.
Do not attempt to implement any of the settings in this guide without first testing them in a non-operational environment. The creators of this guidance assume no responsibility whatsoever for its use by other parties, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic.

Profile Information

Profile TitleCanonical Ubuntu 20.04 LTS Security Technical Implementation Guide (STIG) V1R12
Profile IDxccdf_org.ssgproject.content_profile_stig

CPE Platforms

  • cpe:/o:canonical:ubuntu_linux:20.04::~~lts~~~

Revision History

Current version: 0.1.76

  • draft (as of 2025-01-15)

Table of Contents

  1. System Settings
    1. Installing and Maintaining Software
    2. Account and Access Control
    3. AppArmor
    4. GRUB2 bootloader configuration
    5. Configure Syslog
    6. Network Configuration and Firewalls
    7. File Permissions and Masks
  2. Services
    1. APT service configuration
    2. Base Services
    3. Deprecated services
    4. Network Time Protocol
    5. Obsolete Services
    6. SSH Server
    7. System Security Services Daemon
  3. System Accounting with auditd
    1. Configure auditd Rules for Comprehensive Auditing
    2. Configure auditd Data Retention

Checklist

Group   Guide to the Secure Configuration of Ubuntu 20.04   Group contains 76 groups and 204 rules
Group   System Settings   Group contains 54 groups and 101 rules
[ref]   Contains rules that check correct system settings.
Group   Installing and Maintaining Software   Group contains 13 groups and 13 rules
[ref]   The following sections contain information on security-relevant choices during the initial operating system installation process and the setup of software updates.
Group   System and Software Integrity   Group contains 6 groups and 7 rules
[ref]   System and software integrity can be gained by installing antivirus, increasing system encryption strength with FIPS, verifying installed software, enabling SELinux, installing an Intrusion Prevention System, etc. However, installing or enabling integrity checking tools cannot prevent intrusions, but they can detect that an intrusion may have occurred. Requirements for integrity checking may be highly dependent on the environment in which the system will be used. Snapshot-based approaches such as AIDE may induce considerable overhead in the presence of frequent software updates.
Group   Software Integrity Checking   Group contains 1 group and 5 rules
[ref]   Both the AIDE (Advanced Intrusion Detection Environment) software and the RPM package management system provide mechanisms for verifying the integrity of installed software. AIDE uses snapshots of file metadata (such as hashes) and compares these to current system files in order to detect changes.

The RPM package management system can conduct integrity checks by comparing information in its metadata database with files installed on the system.
Group   Verify Integrity with AIDE   Group contains 5 rules
[ref]   AIDE conducts integrity checks by comparing information about files with previously-gathered information. Ideally, the AIDE database is created immediately after initial system configuration, and then again after any software update. AIDE is highly configurable, with further configuration information located in /usr/share/doc/aide-VERSION .

Rule   Install AIDE   [ref]

The aide package can be installed with the following command:
$ apt-get install aide
Rationale:
The AIDE package must be installed if it is to be available for integrity checking.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_package_aide_installed
References:
cis-csc1, 11, 12, 13, 14, 15, 16, 2, 3, 5, 7, 8, 9
cjis5.10.1.3
cobit5APO01.06, BAI01.06, BAI02.01, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.03, DSS03.05, DSS04.07, DSS05.02, DSS05.03, DSS05.05, DSS05.07, DSS06.02, DSS06.06
disaCCI-002696, CCI-001744
isa-62443-20094.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4
isa-62443-2013SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 4.1, SR 6.2, SR 7.6
ism1034, 1288, 1341, 1417
iso27001-2013A.11.2.4, A.12.1.2, A.12.2.1, A.12.4.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.14.2.7, A.15.2.1, A.8.2.3
nistCM-6(a)
nist-csfDE.CM-1, DE.CM-7, PR.DS-1, PR.DS-6, PR.DS-8, PR.IP-1, PR.IP-3
pcidssReq-11.5
os-srgSRG-OS-000445-GPOS-00199
stigidUBTU-20-010450
cis1.4.1
anssiR76, R79
pcidss411.5.2
stigrefSV-238371r880913_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

DEBIAN_FRONTEND=noninteractive apt-get install -y "aide"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


[[packages]]
name = "aide"
version = "*"

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010450
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - package_aide_installed

- name: Ensure aide is installed
  package:
    name: aide
    state: present
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010450
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - package_aide_installed

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
include install_aide

class install_aide {
  package { 'aide':
    ensure => 'installed',
  }
}

Rule   Build and Test AIDE Database   [ref]

Run the following command to generate a new database:
$ sudo aideinit
By default, the database will be written to the file /var/lib/aide/aide.db.new. Storing the database, the configuration file /etc/aide.conf, and the binary /usr/bin/aide.wrapper (or hashes of these files), in a secure location (such as on read-only media) provides additional assurance about their integrity. The newly-generated database can be installed as follows:
$ sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
To initiate a manual check, run the following command:
$ sudo /usr/bin/aide.wrapper --check
If this check produces any unexpected output, investigate.
Rationale:
For AIDE to be effective, an initial database of "known-good" information about files must be captured and it should be able to be verified against the installed files.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_aide_build_database
References:
cis-csc1, 11, 12, 13, 14, 15, 16, 2, 3, 5, 7, 8, 9
cjis5.10.1.3
cobit5APO01.06, BAI01.06, BAI02.01, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.03, DSS03.05, DSS04.07, DSS05.02, DSS05.03, DSS05.05, DSS05.07, DSS06.02, DSS06.06
disaCCI-002696, CCI-001744
isa-62443-20094.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4
isa-62443-2013SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 4.1, SR 6.2, SR 7.6
iso27001-2013A.11.2.4, A.12.1.2, A.12.2.1, A.12.4.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.14.2.7, A.15.2.1, A.8.2.3
nistCM-6(a)
nist-csfDE.CM-1, DE.CM-7, PR.DS-1, PR.DS-6, PR.DS-8, PR.IP-1, PR.IP-3
pcidssReq-11.5
os-srgSRG-OS-000445-GPOS-00199
stigidUBTU-20-010450
cis1.4.1
anssiR76, R79
pcidss411.5.2
stigrefSV-238371r880913_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

DEBIAN_FRONTEND=noninteractive apt-get install -y "aide"

AIDE_CONFIG=/etc/aide/aide.conf
DEFAULT_DB_PATH=/var/lib/aide/aide.db

# Fix db path in the config file, if necessary
if ! grep -q '^database=file:' ${AIDE_CONFIG}; then
    # replace_or_append gets confused by 'database=file' as a key, so should not be used.
    #replace_or_append "${AIDE_CONFIG}" '^database=file' "${DEFAULT_DB_PATH}" '@CCENUM@' '%s:%s'
    echo "database=file:${DEFAULT_DB_PATH}" >> ${AIDE_CONFIG}
fi

# Fix db out path in the config file, if necessary
if ! grep -q '^database_out=file:' ${AIDE_CONFIG}; then
    echo "database_out=file:${DEFAULT_DB_PATH}.new" >> ${AIDE_CONFIG}
fi

/usr/sbin/aideinit -y -f

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010450
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_build_database
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Build and Test AIDE Database - Ensure AIDE Is Installed
  ansible.builtin.apt:
    name: aide
    state: present
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010450
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_build_database
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Build and Test AIDE Database - Check if DB Path in /etc/aide/aide.conf Is
    Already Set
  ansible.builtin.lineinfile:
    path: /etc/aide/aide.conf
    regexp: ^#?(\s*)(database=)(.*)$
    state: absent
  check_mode: true
  changed_when: false
  register: database_replace
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010450
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_build_database
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Build and Test AIDE Database - Check if DB Out Path in /etc/aide/aide.conf
    Is Already Set
  ansible.builtin.lineinfile:
    path: /etc/aide/aide.conf
    regexp: ^#?(\s*)(database_out=)(.*)$
    state: absent
  check_mode: true
  changed_when: false
  register: database_out_replace
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010450
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_build_database
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Build and Test AIDE Database - Fix DB Path in Config File if Necessary
  ansible.builtin.lineinfile:
    path: /etc/aide/aide.conf
    regexp: ^#?(\s*)(database)(\s*)=(\s*)(.*)$
    line: \2\3=\4file:/var/lib/aide/aide.db
    backrefs: true
  when:
  - '"linux-base" in ansible_facts.packages'
  - database_replace.found > 0
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010450
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_build_database
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Build and Test AIDE Database - Fix DB Out Path in Config File if Necessary
  ansible.builtin.lineinfile:
    path: /etc/aide/aide.conf
    regexp: ^#?(\s*)(database_out)(\s*)=(\s*)(.*)$
    line: \2\3=\4file:/var/lib/aide/aide.db.new
    backrefs: true
  when:
  - '"linux-base" in ansible_facts.packages'
  - database_out_replace.found > 0
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010450
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_build_database
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Build and Test AIDE Database - Ensure the Default DB Path is Added
  ansible.builtin.lineinfile:
    path: /etc/aide/aide.conf
    line: database=file:/var/lib/aide/aide.db
    create: true
  when:
  - '"linux-base" in ansible_facts.packages'
  - database_replace.found == 0
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010450
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_build_database
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Build and Test AIDE Database - Ensure the Default Out Path is Added
  ansible.builtin.lineinfile:
    path: /etc/aide/aide.conf
    line: database_out=file:/var/lib/aide/aide.db.new
    create: true
  when:
  - '"linux-base" in ansible_facts.packages'
  - database_out_replace.found == 0
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010450
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_build_database
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Build and Test AIDE Database - Build and Test AIDE Database
  ansible.builtin.command: /usr/sbin/aideinit -y -f
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010450
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_build_database
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

Rule   Configure AIDE to Verify the Audit Tools   [ref]

The operating system file integrity tool must be configured to protect the integrity of the audit tools.
Rationale:
Protecting the integrity of the tools used for auditing purposes is a critical step toward ensuring the integrity of audit information. Audit information includes all information (e.g., audit records, audit settings, and audit reports) needed to successfully audit information system activity. Audit tools include but are not limited to vendor-provided and open-source audit tools needed to successfully view and manipulate audit information system activity and records. Audit tools include custom queries and report generators. It is not uncommon for attackers to replace the audit tools or inject code into the existing tools to provide the capability to hide or erase system activity from the audit logs. To address this risk, audit tools must be cryptographically signed to provide the capability to identify when the audit tools have been modified, manipulated, or replaced. An example is a checksum hash of the file or files.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_aide_check_audit_tools
References:
disaCCI-001496, CCI-001494, CCI-001495, CCI-001493
nistAU-9(3), AU-9(3).1
os-srgSRG-OS-000278-GPOS-00108
stigidUBTU-20-010205
stigrefSV-238303r877393_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

DEBIAN_FRONTEND=noninteractive apt-get install -y "aide"










if grep -i '^.*/usr/sbin/auditctl.*$' /etc/aide/aide.conf; then
sed -i "s#.*/usr/sbin/auditctl.*#/usr/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512#" /etc/aide/aide.conf
else
echo "/usr/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512" >> /etc/aide/aide.conf
fi

if grep -i '^.*/usr/sbin/auditd.*$' /etc/aide/aide.conf; then
sed -i "s#.*/usr/sbin/auditd.*#/usr/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512#" /etc/aide/aide.conf
else
echo "/usr/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512" >> /etc/aide/aide.conf
fi

if grep -i '^.*/usr/sbin/ausearch.*$' /etc/aide/aide.conf; then
sed -i "s#.*/usr/sbin/ausearch.*#/usr/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512#" /etc/aide/aide.conf
else
echo "/usr/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512" >> /etc/aide/aide.conf
fi

if grep -i '^.*/usr/sbin/aureport.*$' /etc/aide/aide.conf; then
sed -i "s#.*/usr/sbin/aureport.*#/usr/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512#" /etc/aide/aide.conf
else
echo "/usr/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512" >> /etc/aide/aide.conf
fi

if grep -i '^.*/usr/sbin/autrace.*$' /etc/aide/aide.conf; then
sed -i "s#.*/usr/sbin/autrace.*#/usr/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512#" /etc/aide/aide.conf
else
echo "/usr/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512" >> /etc/aide/aide.conf
fi

if grep -i '^.*/usr/sbin/augenrules.*$' /etc/aide/aide.conf; then
sed -i "s#.*/usr/sbin/augenrules.*#/usr/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512#" /etc/aide/aide.conf
else
echo "/usr/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512" >> /etc/aide/aide.conf
fi

if grep -i '^.*/usr/sbin/audispd.*$' /etc/aide/aide.conf; then
sed -i "s#.*/usr/sbin/audispd.*#/usr/sbin/audispd p+i+n+u+g+s+b+acl+xattrs+sha512#" /etc/aide/aide.conf
else
echo "/usr/sbin/audispd p+i+n+u+g+s+b+acl+xattrs+sha512" >> /etc/aide/aide.conf
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010205
  - NIST-800-53-AU-9(3)
  - NIST-800-53-AU-9(3).1
  - aide_check_audit_tools
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Configure AIDE to Verify the Audit Tools - Gather List of Packages
  tags:
  - DISA-STIG-UBTU-20-010205
  - NIST-800-53-AU-9(3)
  - NIST-800-53-AU-9(3).1
  - aide_check_audit_tools
  - aide_check_audit_tools
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  ansible.builtin.package_facts:
    manager: auto
  when: '"linux-base" in ansible_facts.packages'

- name: Ensure aide is installed
  package:
    name: '{{ item }}'
    state: present
  with_items:
  - aide
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010205
  - NIST-800-53-AU-9(3)
  - NIST-800-53-AU-9(3).1
  - aide_check_audit_tools
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Set audit_tools fact
  set_fact:
    audit_tools:
    - /usr/sbin/audispd
    - /usr/sbin/auditctl
    - /usr/sbin/auditd
    - /usr/sbin/augenrules
    - /usr/sbin/aureport
    - /usr/sbin/ausearch
    - /usr/sbin/autrace
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010205
  - NIST-800-53-AU-9(3)
  - NIST-800-53-AU-9(3).1
  - aide_check_audit_tools
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure existing AIDE configuration for audit tools are correct
  lineinfile:
    path: /etc/aide/aide.conf
    regexp: ^{{ item }}\s
    line: '{{ item }} p+i+n+u+g+s+b+acl+xattrs+sha512'
  with_items: '{{ audit_tools }}'
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010205
  - NIST-800-53-AU-9(3)
  - NIST-800-53-AU-9(3).1
  - aide_check_audit_tools
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Configure AIDE to properly protect audit tools
  lineinfile:
    path: /etc/aide/aide.conf
    line: '{{ item }} p+i+n+u+g+s+b+acl+xattrs+sha512'
  with_items: '{{ audit_tools }}'
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010205
  - NIST-800-53-AU-9(3)
  - NIST-800-53-AU-9(3).1
  - aide_check_audit_tools
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

Rule   Configure AIDE To Notify Personnel if Baseline Configurations Are Altered   [ref]

The operating system file integrity tool must be configured to notify designated personnel of any changes to configurations.
Rationale:
Detecting changes in the system can help avoid unintended, and negative consequences that could affect the security state of the operating system
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_aide_disable_silentreports
References:
disaCCI-001744, CCI-002702
os-srgSRG-OS-000447-GPOS-00201, SRG-OS-000363-GPOS-00150
stigidUBTU-20-010451
stigrefSV-238372r853449_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

if [ -e "/etc/default/aide" ] ; then
    
    LC_ALL=C sed -i "/^\s*SILENTREPORTS=/Id" "/etc/default/aide"
else
    touch "/etc/default/aide"
fi
# make sure file has newline at the end
sed -i -e '$a\' "/etc/default/aide"

cp "/etc/default/aide" "/etc/default/aide.bak"
# Insert at the end of the file
printf '%s\n' "SILENTREPORTS=no" >> "/etc/default/aide"
# Clean up after ourselves.
rm "/etc/default/aide.bak"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010451
  - aide_disable_silentreports
  - configure_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Configure AIDE To Notify Personnel if Baseline Configurations Are Altered
  block:

  - name: Check for duplicate values
    lineinfile:
      path: /etc/default/aide
      create: true
      regexp: (?i)^\s*SILENTREPORTS=
      state: absent
    check_mode: true
    changed_when: false
    register: dupes

  - name: Deduplicate values from /etc/default/aide
    lineinfile:
      path: /etc/default/aide
      create: true
      regexp: (?i)^\s*SILENTREPORTS=
      state: absent
    when: dupes.found is defined and dupes.found > 1

  - name: Insert correct line to /etc/default/aide
    lineinfile:
      path: /etc/default/aide
      create: true
      regexp: (?i)^\s*SILENTREPORTS=
      line: SILENTREPORTS=no
      state: present
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010451
  - aide_disable_silentreports
  - configure_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Configure Periodic Execution of AIDE   [ref]

At a minimum, AIDE should be configured to run a weekly scan. To implement a daily execution of AIDE at 4:05am using cron, add the following line to /etc/crontab:
05 4 * * * root /usr/bin/aide.wrapper --config /etc/aide/aide.conf --check
To implement a weekly execution of AIDE at 4:05am using cron, add the following line to /etc/crontab:
05 4 * * 0 root /usr/bin/aide.wrapper --config /etc/aide/aide.conf --check
AIDE can be executed periodically through other means; this is merely one example. The usage of cron's special time codes, such as @daily and @weekly is acceptable.
Rationale:
By default, AIDE does not install itself for periodic execution. Periodically running AIDE is necessary to reveal unexpected changes in installed files.

Unauthorized changes to the baseline configuration could make the system vulnerable to various attacks or allow unauthorized access to the operating system. Changes to operating system configurations can have unintended side effects, some of which may be relevant to security.

Detecting such changes and providing an automated response can help avoid unintended, negative consequences that could ultimately affect the security state of the operating system. The operating system's Information Management Officer (IMO)/Information System Security Officer (ISSO) and System Administrators (SAs) must be notified via email and/or monitoring system trap when there is an unauthorized modification of a configuration item.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_aide_periodic_cron_checking
References:
cis-csc1, 11, 12, 13, 14, 15, 16, 2, 3, 5, 7, 8, 9
cjis5.10.1.3
cobit5APO01.06, BAI01.06, BAI02.01, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.03, DSS03.05, DSS04.07, DSS05.02, DSS05.03, DSS05.05, DSS05.07, DSS06.02, DSS06.06
disaCCI-002702, CCI-001744, CCI-002699
isa-62443-20094.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4
isa-62443-2013SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 4.1, SR 6.2, SR 7.6
iso27001-2013A.11.2.4, A.12.1.2, A.12.2.1, A.12.4.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.14.2.7, A.15.2.1, A.8.2.3
nistSI-7, SI-7(1), CM-6(a)
nist-csfDE.CM-1, DE.CM-7, PR.DS-1, PR.DS-6, PR.DS-8, PR.IP-1, PR.IP-3
pcidssReq-11.5
os-srgSRG-OS-000363-GPOS-00150, SRG-OS-000446-GPOS-00200, SRG-OS-000447-GPOS-00201
stigidUBTU-20-010074
cis1.4.2
anssiR76
pcidss411.5.2
stigrefSV-238236r853415_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

DEBIAN_FRONTEND=noninteractive apt-get install -y "aide"

# AiDE usually adds its own cron jobs to /etc/cron.daily. If script is there, this rule is
# compliant. Otherwise, we copy the script to the /etc/cron.weekly
if ! grep -Eq '^(\/usr\/bin\/)?aide(\.wrapper)?\s+' /etc/cron.*/*; then
    cp -f /usr/share/aide/config/cron.daily/aide /etc/cron.weekly/
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010074
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SI-7
  - NIST-800-53-SI-7(1)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_periodic_cron_checking
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure AIDE is installed
  package:
    name: '{{ item }}'
    state: present
  with_items:
  - aide
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010074
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SI-7
  - NIST-800-53-SI-7(1)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_periodic_cron_checking
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Set cron package name - RedHat
  set_fact:
    cron_pkg_name: cronie
  when:
  - '"linux-base" in ansible_facts.packages'
  - ansible_os_family == "RedHat" or ansible_os_family == "Suse"
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010074
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SI-7
  - NIST-800-53-SI-7(1)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_periodic_cron_checking
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Set cron package name - Debian
  set_fact:
    cron_pkg_name: cron
  when:
  - '"linux-base" in ansible_facts.packages'
  - ansible_os_family == "Debian"
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010074
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SI-7
  - NIST-800-53-SI-7(1)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_periodic_cron_checking
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Install cron
  package:
    name: '{{ cron_pkg_name }}'
    state: present
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010074
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SI-7
  - NIST-800-53-SI-7(1)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_periodic_cron_checking
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Configure Periodic Execution of AIDE
  cron:
    name: run AIDE check
    minute: 5
    hour: 4
    weekday: 0
    user: root
    job: /usr/bin/aide.wrapper --check
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - CJIS-5.10.1.3
  - DISA-STIG-UBTU-20-010074
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SI-7
  - NIST-800-53-SI-7(1)
  - PCI-DSS-Req-11.5
  - PCI-DSSv4-11.5.2
  - aide_periodic_cron_checking
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
Group   Federal Information Processing Standard (FIPS)   Group contains 1 rule
[ref]   The Federal Information Processing Standard (FIPS) is a computer security standard which is developed by the U.S. Government and industry working groups to validate the quality of cryptographic modules. The FIPS standard provides four security levels to ensure adequate coverage of different industries, implementation of cryptographic modules, and organizational sizes and requirements.

FIPS 140-2 is the current standard for validating that mechanisms used to access cryptographic modules utilize authentication that meets industry and government requirements. For government systems, this allows Security Levels 1, 2, 3, or 4 for use on Ubuntu 20.04.

See http://csrc.nist.gov/publications/PubsFIPS.html for more information.

Rule   Verify '/proc/sys/crypto/fips_enabled' exists   [ref]

On a system where FIPS 140-2 mode is enabled, /proc/sys/crypto/fips_enabled must exist. To verify FIPS mode, run the following command:
cat /proc/sys/crypto/fips_enabled
Warning:  To configure the OS to run in FIPS 140-2 mode, the kernel parameter "fips=1" needs to be added during its installation. Enabling FIPS mode on a preexisting system involves a number of modifications to it. Refer to the vendor installation guidances.
Warning:  System Crypto Modules must be provided by a vendor that undergoes FIPS-140 certifications. FIPS-140 is applicable to all Federal agencies that use cryptographic-based security systems to protect sensitive information in computer and telecommunication systems (including voice systems) as defined in Section 5131 of the Information Technology Management Reform Act of 1996, Public Law 104-106. This standard shall be used in designing and implementing cryptographic modules that Federal departments and agencies operate or are operated for them under contract. See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.140-2.pdf To meet this, the system has to have cryptographic software provided by a vendor that has undergone this certification. This means providing documentation, test results, design information, and independent third party review by an accredited lab. While open source software is capable of meeting this, it does not meet FIPS-140 unless the vendor submits to this process.
Rationale:
Use of weak or untested encryption algorithms undermines the purposes of utilizing encryption to protect data. The operating system must implement cryptographic modules adhering to the higher standards approved by the federal government since this provides assurance they have been tested and validated.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_is_fips_mode_enabled
References:
disaCCI-002450
nistSC-12(2), SC-12(3), SC-13
os-srgSRG-OS-000396-GPOS-00176, SRG-OS-000478-GPOS-00223
stigidUBTU-20-010442
stigrefSV-238363r880881_rule
Group   Endpoint Protection Software   Group contains 2 groups and 1 rule
[ref]   Endpoint protection security software that is not provided or supported by Canonical can be installed to provide complementary or duplicative security capabilities to those provided by the base platform. Add-on software may not be appropriate for some specialized systems.
Group   McAfee Endpoint Security Software   Group contains 1 group and 1 rule
[ref]   In DoD environments, McAfee Host-based Security System (HBSS) and VirusScan Enterprise for Linux (VSEL) is required to be installed on all systems.
Group   McAfee Endpoint Security for Linux (ENSL)   Group contains 1 rule
[ref]   McAfee Endpoint Security for Linux (ENSL) is a suite of software applications used to monitor, detect, and defend computer networks and systems.

Rule   Install McAfee Endpoint Security for Linux (ENSL)   [ref]

Install McAfee Endpoint Security for Linux antivirus software which is provided for DoD systems and uses signatures to search for the presence of viruses on the filesystem. The mfetp package can be installed with the following command:
$ apt-get install mfetp
Warning:  Due to McAfee Endpoint Security for Linux (ENSL) being 3rd party software, automated remediation is not available for this configuration check.
Rationale:
Virus scanning software can be used to detect if a system has been compromised by computer viruses, as well as to limit their spread to other systems.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_package_mcafeetp_installed
References:
disaCCI-001263, CCI-000366
nistSI-2(2)
os-srgSRG-OS-000191-GPOS-00080
stigidUBTU-20-010415
stigrefSV-238336r939261_rule
Group   Disk Partitioning   Group contains 1 rule
[ref]   To ensure separation and protection of data, there are top-level system directories which should be placed on their own physical partition or logical volume. The installer's default partitioning scheme creates separate logical volumes for /, /boot, and swap.
  • If starting with any of the default layouts, check the box to \"Review and modify partitioning.\" This allows for the easy creation of additional logical volumes inside the volume group already created, though it may require making /'s logical volume smaller to create space. In general, using logical volumes is preferable to using partitions because they can be more easily adjusted later.
  • If creating a custom layout, create the partitions mentioned in the previous paragraph (which the installer will require anyway), as well as separate ones described in the following sections.
If a system has already been installed, and the default partitioning scheme was used, it is possible but nontrivial to modify it to create separate logical volumes for the directories listed above. The Logical Volume Manager (LVM) makes this possible.

Rule   Encrypt Partitions   [ref]

Ubuntu 20.04 natively supports partition encryption through the Linux Unified Key Setup-on-disk-format (LUKS) technology. The easiest way to encrypt a partition is during installation time.

For manual installations, select the Encrypt checkbox during partition creation to encrypt the partition. When this option is selected the system will prompt for a passphrase to use in decrypting the partition. The passphrase will subsequently need to be entered manually every time the system boots.

Detailed information on encrypting partitions using LUKS or LUKS ciphers can be found on the Ubuntu 20.04 Documentation web site:
https://help.ubuntu.com/community/Full_Disk_Encryption_Howto_2019 .
Rationale:
The risk of a system's physical compromise, particularly mobile systems such as laptops, places its data at risk of compromise. Encrypting this data mitigates the risk of its loss if the system is lost.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_encrypt_partitions
References:
cis-csc13, 14
cobit5APO01.06, BAI02.01, BAI06.01, DSS04.07, DSS05.03, DSS05.04, DSS05.07, DSS06.02, DSS06.06
cui3.13.16
disaCCI-002476, CCI-001199, CCI-002475
hipaa164.308(a)(1)(ii)(D), 164.308(b)(1), 164.310(d), 164.312(a)(1), 164.312(a)(2)(iii), 164.312(a)(2)(iv), 164.312(b), 164.312(c), 164.314(b)(2)(i), 164.312(d)
isa-62443-2013SR 3.4, SR 4.1, SR 5.2
iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
nerc-cipCIP-003-8 R4.2, CIP-007-3 R5.1
nistCM-6(a), SC-28, SC-28(1), SC-13, AU-9(3)
nist-csfPR.DS-1, PR.DS-5
os-srgSRG-OS-000405-GPOS-00184, SRG-OS-000185-GPOS-00079, SRG-OS-000404-GPOS-00183
stigidUBTU-20-010414
stigrefSV-238335r951548_rule
Group   GNOME Desktop Environment   Group contains 2 groups and 3 rules
[ref]   GNOME is a graphical desktop environment bundled with many Linux distributions that allow users to easily interact with the operating system graphically rather than textually. The GNOME Graphical Display Manager (GDM) provides login, logout, and user switching contexts as well as display server management.

GNOME is developed by the GNOME Project and is considered the default Red Hat Graphical environment.

For more information on GNOME and the GNOME Project, see https://www.gnome.org.
Group   Configure GNOME Screen Locking   Group contains 1 rule
[ref]   In the default GNOME3 desktop, the screen can be locked by selecting the user name in the far right corner of the main panel and selecting Lock.

The following sections detail commands to enforce idle activation of the screensaver, screen locking, a blank-screen screensaver, and an idle activation time.

Because users should be trained to lock the screen when they step away from the computer, the automatic locking feature is only meant as a backup.

The root account can be screen-locked; however, the root account should never be used to log into an X Windows environment and should only be used to for direct login via console in emergency circumstances.

For more information about enforcing preferences in the GNOME3 environment using the DConf configuration system, see http://wiki.gnome.org/dconf and the man page dconf(1).

Rule   Enable GNOME3 Screensaver Lock After Idle Period   [ref]

To activate locking of the screensaver in the GNOME3 desktop when it is activated, add or set lock-enabled to true in /etc/dconf/db/local.d/00-security-settings. For example:
[org/gnome/desktop/screensaver]
lock-enabled=true
Once the settings have been added, add a lock to /etc/dconf/db/local.d/locks/00-security-settings-lock to prevent user modification. For example:
/org/gnome/desktop/screensaver/lock-enabled
After the settings have been set, run dconf update.
Rationale:
A session lock is a temporary action taken when a user stops work and moves away from the immediate physical vicinity of the information system but does not want to logout because of the temporary nature of the absense.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_dconf_gnome_screensaver_lock_enabled
References:
cis-csc1, 12, 15, 16
cjis5.5.5
cobit5DSS05.04, DSS05.10, DSS06.10
cui3.1.10
disaCCI-000057, CCI-000056
isa-62443-20094.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9
iso27001-2013A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3
nistCM-6(a)
nist-csfPR.AC-7
pcidssReq-8.1.8
os-srgSRG-OS-000028-GPOS-00009, SRG-OS-000030-GPOS-00011
stigidUBTU-20-010004
pcidss48.2.8, 8.2
stigrefSV-238199r653772_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'gdm3' 2>/dev/null | grep -q installed && { [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; }; then

mkdir -p /etc/dconf/profile
dconf_profile_path=/etc/dconf/profile/user

[[ -s "${dconf_profile_path}" ]] || echo > "${dconf_profile_path}"

if ! grep -Pzq "(?s)^\s*user-db:user.*\n\s*system-db:local" "${dconf_profile_path}"; then
    sed -i --follow-symlinks "1s/^/user-db:user\nsystem-db:local\n/" "${dconf_profile_path}"
fi

# Make sure the corresponding directories exist
mkdir -p /etc/dconf/db/local.d

# Make sure permissions allow regular users to read dconf settings.
# Also define the umask to avoid `dconf update` changing permissions.
chmod -R u=rwX,go=rX /etc/dconf/profile
(umask 0022 && dconf update)
mkdir -p /etc/dconf/profile
dconf_profile_path=/etc/dconf/profile/gdm

[[ -s "${dconf_profile_path}" ]] || echo > "${dconf_profile_path}"

if ! grep -Pzq "(?s)^\s*user-db:user.*\n\s*system-db:gdm" "${dconf_profile_path}"; then
    sed -i --follow-symlinks "1s/^/user-db:user\nsystem-db:gdm\n/" "${dconf_profile_path}"
fi

# Make sure the corresponding directories exist
mkdir -p /etc/dconf/db/gdm.d

# Make sure permissions allow regular users to read dconf settings.
# Also define the umask to avoid `dconf update` changing permissions.
chmod -R u=rwX,go=rX /etc/dconf/profile
(umask 0022 && dconf update)



# Check for setting in any of the DConf db directories
# If files contain ibus or distro, ignore them.
# The assignment assumes that individual filenames don't contain :
readarray -t SETTINGSFILES < <(grep -r "\\[org/gnome/desktop/screensaver\\]" "/etc/dconf/db/" \
                                | grep -v 'distro\|ibus\|local.d' | cut -d":" -f1)
DCONFFILE="/etc/dconf/db/local.d/00-security-settings"
DBDIR="/etc/dconf/db/local.d"

mkdir -p "${DBDIR}"

# Comment out the configurations in databases different from the target one
if [ "${#SETTINGSFILES[@]}" -ne 0 ]
then
    if grep -q "^\\s*lock-enabled\\s*=" "${SETTINGSFILES[@]}"
    then
        
        sed -Ei "s/(^\s*)lock-enabled(\s*=)/#\1lock-enabled\2/g" "${SETTINGSFILES[@]}"
    fi
fi

[ ! -z "${DCONFFILE}" ] && echo "" >> "${DCONFFILE}"
if ! grep -q "\\[org/gnome/desktop/screensaver\\]" "${DCONFFILE}"
then
    printf '%s\n' "[org/gnome/desktop/screensaver]" >> ${DCONFFILE}
fi

escaped_value="$(sed -e 's/\\/\\\\/g' <<< "true")"
if grep -q "^\\s*lock-enabled\\s*=" "${DCONFFILE}"
then
        sed -i "s/\\s*lock-enabled\\s*=\\s*.*/lock-enabled=${escaped_value}/g" "${DCONFFILE}"
    else
        sed -i "\\|\\[org/gnome/desktop/screensaver\\]|a\\lock-enabled=${escaped_value}" "${DCONFFILE}"
fi
# Make sure permissions allow regular users to read dconf settings.
# Also define the umask to avoid `dconf update` changing permissions.
chmod -R u=rwX,go=rX /etc/dconf/db
(umask 0022 && dconf update)
# Check for setting in any of the DConf db directories
LOCKFILES=$(grep -r "^/org/gnome/desktop/screensaver/lock-enabled$" "/etc/dconf/db/" \
            | grep -v 'distro\|ibus\|local.d' | grep ":" | cut -d":" -f1)
LOCKSFOLDER="/etc/dconf/db/local.d/locks"

mkdir -p "${LOCKSFOLDER}"

# Comment out the configurations in databases different from the target one
if [[ ! -z "${LOCKFILES}" ]]
then
    sed -i -E "s|^/org/gnome/desktop/screensaver/lock-enabled$|#&|" "${LOCKFILES[@]}"
fi

if ! grep -qr "^/org/gnome/desktop/screensaver/lock-enabled$" /etc/dconf/db/local.d/
then
    echo "/org/gnome/desktop/screensaver/lock-enabled" >> "/etc/dconf/db/local.d/locks/00-security-settings-lock"
fi
# Make sure permissions allow regular users to read dconf settings.
# Also define the umask to avoid `dconf update` changing permissions.
chmod -R u=rwX,go=rX /etc/dconf/db
(umask 0022 && dconf update)

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
Group   GNOME System Settings   Group contains 1 rule
[ref]   GNOME provides configuration and functionality to a graphical desktop environment that changes grahical configurations or allow a user to perform actions that users normally would not be able to do in non-graphical mode such as remote access configuration, power policies, Geo-location, etc. Configuring such settings in GNOME will prevent accidential graphical configuration changes by users from taking place.

Rule   Disable Ctrl-Alt-Del Reboot Key Sequence in GNOME3   [ref]

By default, GNOME will reboot the system if the Ctrl-Alt-Del key sequence is pressed.

To configure the system to ignore the Ctrl-Alt-Del key sequence from the Graphical User Interface (GUI) instead of rebooting the system, add or set logout to [''] in /etc/dconf/db/local.d/00-security-settings. For example:
[org/gnome/settings-daemon/plugins/media-keys]
logout=['']
Once the settings have been added, add a lock to /etc/dconf/db/local.d/locks/00-security-settings-lock to prevent user modification. For example:
/org/gnome/settings-daemon/plugins/media-keys/logout
After the settings have been set, run dconf update.
Rationale:
A locally logged-in user who presses Ctrl-Alt-Del, when at the console, can reboot the system. If accidentally pressed, as could happen in the case of mixed OS environment, this can create the risk of short-term loss of availability of systems due to unintentional reboot.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_dconf_gnome_disable_ctrlaltdel_reboot
References:
cis-csc12, 13, 14, 15, 16, 18, 3, 5
cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
cui3.1.2
disaCCI-000366
isa-62443-20094.3.3.7.3
isa-62443-2013SR 2.1, SR 5.2
iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
nistCM-6(a), AC-6(1), CM-7(b)
nist-csfPR.AC-4, PR.DS-5
os-srgSRG-OS-000480-GPOS-00227
stigidUBTU-20-010459
stigrefSV-238379r654312_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'gdm3' 2>/dev/null | grep -q installed && { [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; }; then

mkdir -p /etc/dconf/profile
dconf_profile_path=/etc/dconf/profile/user

[[ -s "${dconf_profile_path}" ]] || echo > "${dconf_profile_path}"

if ! grep -Pzq "(?s)^\s*user-db:user.*\n\s*system-db:local" "${dconf_profile_path}"; then
    sed -i --follow-symlinks "1s/^/user-db:user\nsystem-db:local\n/" "${dconf_profile_path}"
fi

# Make sure the corresponding directories exist
mkdir -p /etc/dconf/db/local.d

# Make sure permissions allow regular users to read dconf settings.
# Also define the umask to avoid `dconf update` changing permissions.
chmod -R u=rwX,go=rX /etc/dconf/profile
(umask 0022 && dconf update)
mkdir -p /etc/dconf/profile
dconf_profile_path=/etc/dconf/profile/gdm

[[ -s "${dconf_profile_path}" ]] || echo > "${dconf_profile_path}"

if ! grep -Pzq "(?s)^\s*user-db:user.*\n\s*system-db:gdm" "${dconf_profile_path}"; then
    sed -i --follow-symlinks "1s/^/user-db:user\nsystem-db:gdm\n/" "${dconf_profile_path}"
fi

# Make sure the corresponding directories exist
mkdir -p /etc/dconf/db/gdm.d

# Make sure permissions allow regular users to read dconf settings.
# Also define the umask to avoid `dconf update` changing permissions.
chmod -R u=rwX,go=rX /etc/dconf/profile
(umask 0022 && dconf update)


# Check for setting in any of the DConf db directories
# If files contain ibus or distro, ignore them.
# The assignment assumes that individual filenames don't contain :
readarray -t SETTINGSFILES < <(grep -r "\\[org/gnome/settings-daemon/plugins/media-keys\\]" "/etc/dconf/db/" \
                                | grep -v 'distro\|ibus\|local.d' | cut -d":" -f1)
DCONFFILE="/etc/dconf/db/local.d/00-security-settings"
DBDIR="/etc/dconf/db/local.d"

mkdir -p "${DBDIR}"

# Comment out the configurations in databases different from the target one
if [ "${#SETTINGSFILES[@]}" -ne 0 ]
then
    if grep -q "^\\s*logout\\s*=" "${SETTINGSFILES[@]}"
    then
        
        sed -Ei "s/(^\s*)logout(\s*=)/#\1logout\2/g" "${SETTINGSFILES[@]}"
    fi
fi

[ ! -z "${DCONFFILE}" ] && echo "" >> "${DCONFFILE}"
if ! grep -q "\\[org/gnome/settings-daemon/plugins/media-keys\\]" "${DCONFFILE}"
then
    printf '%s\n' "[org/gnome/settings-daemon/plugins/media-keys]" >> ${DCONFFILE}
fi

escaped_value="$(sed -e 's/\\/\\\\/g' <<< "['']")"
if grep -q "^\\s*logout\\s*=" "${DCONFFILE}"
then
        sed -i "s/\\s*logout\\s*=\\s*.*/logout=${escaped_value}/g" "${DCONFFILE}"
    else
        sed -i "\\|\\[org/gnome/settings-daemon/plugins/media-keys\\]|a\\logout=${escaped_value}" "${DCONFFILE}"
fi
# Make sure permissions allow regular users to read dconf settings.
# Also define the umask to avoid `dconf update` changing permissions.
chmod -R u=rwX,go=rX /etc/dconf/db
(umask 0022 && dconf update)
# Check for setting in any of the DConf db directories
LOCKFILES=$(grep -r "^/org/gnome/settings-daemon/plugins/media-keys/logout$" "/etc/dconf/db/" \
            | grep -v 'distro\|ibus\|local.d' | grep ":" | cut -d":" -f1)
LOCKSFOLDER="/etc/dconf/db/local.d/locks"

mkdir -p "${LOCKSFOLDER}"

# Comment out the configurations in databases different from the target one
if [[ ! -z "${LOCKFILES}" ]]
then
    sed -i -E "s|^/org/gnome/settings-daemon/plugins/media-keys/logout$|#&|" "${LOCKFILES[@]}"
fi

if ! grep -qr "^/org/gnome/settings-daemon/plugins/media-keys/logout$" /etc/dconf/db/local.d/
then
    echo "/org/gnome/settings-daemon/plugins/media-keys/logout" >> "/etc/dconf/db/local.d/locks/00-security-settings-lock"
fi
# Make sure permissions allow regular users to read dconf settings.
# Also define the umask to avoid `dconf update` changing permissions.
chmod -R u=rwX,go=rX /etc/dconf/db
(umask 0022 && dconf update)

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
Group   Sudo   Group contains 1 rule
[ref]   Sudo, which stands for "su 'do'", provides the ability to delegate authority to certain users, groups of users, or system administrators. When configured for system users and/or groups, Sudo can allow a user or group to execute privileged commands that normally only root is allowed to execute.

For more information on Sudo and addition Sudo configuration options, see https://www.sudo.ws.

Rule   Ensure Users Re-Authenticate for Privilege Escalation - sudo   [ref]

The sudo NOPASSWD and !authenticate option, when specified, allows a user to execute commands using sudo without having to authenticate. This should be disabled by making sure that NOPASSWD and/or !authenticate do not exist in /etc/sudoers configuration file or any sudo configuration snippets in /etc/sudoers.d/."
Rationale:
Without re-authentication, users may access resources or perform tasks for which they do not have authorization.

When operating systems provide the capability to escalate a functional capability, it is critical that the user re-authenticate.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_sudo_require_authentication
References:
cis-csc1, 12, 15, 16, 5
cobit5DSS05.04, DSS05.10, DSS06.03, DSS06.10
disaCCI-002038, CCI-004895
isa-62443-20094.3.3.5.1, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9
iso27001-2013A.18.1.4, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
nistIA-11, CM-6(a)
nist-csfPR.AC-1, PR.AC-7
os-srgSRG-OS-000373-GPOS-00156
stigidUBTU-20-010014
pcidss42.2.6, 2.2
stigrefSV-238208r853405_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict

for f in /etc/sudoers /etc/sudoers.d/* ; do
  if [ ! -e "$f" ] ; then
    continue
  fi
  matching_list=$(grep -P '^(?!#).*[\s]+NOPASSWD[\s]*\:.*$' $f | uniq )
  if ! test -z "$matching_list"; then
    while IFS= read -r entry; do
      # comment out "NOPASSWD" matches to preserve user data
      sed -i "s/^${entry}$/# &/g" $f
    done <<< "$matching_list"

    /usr/sbin/visudo -cf $f &> /dev/null || echo "Fail to validate $f with visudo"
  fi
done

for f in /etc/sudoers /etc/sudoers.d/* ; do
  if [ ! -e "$f" ] ; then
    continue
  fi
  matching_list=$(grep -P '^(?!#).*[\s]+\!authenticate.*$' $f | uniq )
  if ! test -z "$matching_list"; then
    while IFS= read -r entry; do
      # comment out "!authenticate" matches to preserve user data
      sed -i "s/^${entry}$/# &/g" $f
    done <<< "$matching_list"

    /usr/sbin/visudo -cf $f &> /dev/null || echo "Fail to validate $f with visudo"
  fi
done

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Find /etc/sudoers.d/ files
  ansible.builtin.find:
    paths:
    - /etc/sudoers.d/
  register: sudoers
  tags:
  - DISA-STIG-UBTU-20-010014
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-11
  - PCI-DSSv4-2.2
  - PCI-DSSv4-2.2.6
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - sudo_require_authentication

- name: Remove lines containing NOPASSWD from sudoers files
  ansible.builtin.replace:
    regexp: (^(?!#).*[\s]+NOPASSWD[\s]*\:.*$)
    replace: '# \g<1>'
    path: '{{ item.path }}'
    validate: /usr/sbin/visudo -cf %s
  with_items:
  - path: /etc/sudoers
  - '{{ sudoers.files }}'
  tags:
  - DISA-STIG-UBTU-20-010014
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-11
  - PCI-DSSv4-2.2
  - PCI-DSSv4-2.2.6
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - sudo_require_authentication

- name: Find /etc/sudoers.d/ files
  ansible.builtin.find:
    paths:
    - /etc/sudoers.d/
  register: sudoers
  tags:
  - DISA-STIG-UBTU-20-010014
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-11
  - PCI-DSSv4-2.2
  - PCI-DSSv4-2.2.6
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - sudo_require_authentication

- name: Remove lines containing !authenticate from sudoers files
  ansible.builtin.replace:
    regexp: (^(?!#).*[\s]+\!authenticate.*$)
    replace: '# \g<1>'
    path: '{{ item.path }}'
    validate: /usr/sbin/visudo -cf %s
  with_items:
  - path: /etc/sudoers
  - '{{ sudoers.files }}'
  tags:
  - DISA-STIG-UBTU-20-010014
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-11
  - PCI-DSSv4-2.2
  - PCI-DSSv4-2.2.6
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - sudo_require_authentication
Group   Updating Software   Group contains 1 rule
[ref]   The apt_get command line tool is used to install and update software packages. The system also provides a graphical software update tool in the System menu, in the Administration submenu, called Software Update.

Ubuntu 20.04 systems contain an installed software catalog called the RPM database, which records metadata of installed packages. Consistently using apt_get or the graphical Software Update for all software installation allows for insight into the current inventory of installed software on the system.

Rule   Ensure apt_get Removes Previous Package Versions   [ref]

apt_get should be configured to remove previous software components after new versions have been installed. To configure apt_get to remove the previous software components after updating, set the ::Remove-Unused-Dependencies and ::Remove-Unused-Kernel-Packages to true in /etc/apt/apt.conf.
Rationale:
Previous versions of software components that are not removed from the information system after updates have been installed may be exploited by some adversaries.
Severity: 
low
Rule ID:xccdf_org.ssgproject.content_rule_clean_components_post_updating
References:
cis-csc18, 20, 4
cobit5APO12.01, APO12.02, APO12.03, APO12.04, BAI03.10, DSS05.01, DSS05.02
cui3.4.8
disaCCI-002617
isa-62443-20094.2.3, 4.2.3.12, 4.2.3.7, 4.2.3.9
iso27001-2013A.12.6.1, A.14.2.3, A.16.1.3, A.18.2.2, A.18.2.3
nistSI-2(6), CM-11(a), CM-11(b), CM-6(a)
nist-csfID.RA-1, PR.IP-12
os-srgSRG-OS-000437-GPOS-00194
stigidUBTU-20-010449
stigrefSV-238370r853447_rule


flag1=1
flag2=1

for file in /etc/apt/apt.conf.d/*; do
    if [ -e "$file" ]; then
        if grep -qi "Unattended-Upgrade::Remove-Unused-Dependencies" $file; then
            sed -i --follow-symlinks "s/^.*Unattended-Upgrade::Remove-Unused-Dependencies.*/Unattended-Upgrade::Remove-Unused-Dependencies \"true\";/I" $file
            flag1=0
        fi

        if grep -qi "Unattended-Upgrade::Remove-Unused-Kernel-Packages" $file; then
            sed -i --follow-symlinks "s/^.*Unattended-Upgrade::Remove-Unused-Kernel-Packages.*/Unattended-Upgrade::Remove-Unused-Kernel-Packages \"true\";/I" $file
            flag2=0
        fi
    fi
done

if [ $flag1 ] || [ $flag2 ]; then
    echo "Unattended-Upgrade::Remove-Unused-Dependencies \"true\";" >> /etc/apt/apt.conf.d/50unattended-upgrades
    echo "Unattended-Upgrade::Remove-Unused-Kernel-Packages \"true\";" >> /etc/apt/apt.conf.d/50unattended-upgrades
fi
Group   Account and Access Control   Group contains 18 groups and 44 rules
[ref]   In traditional Unix security, if an attacker gains shell access to a certain login account, they can perform any action or access any file to which that account has access. Therefore, making it more difficult for unauthorized people to gain shell access to accounts, particularly to privileged accounts, is a necessary part of securing a system. This section introduces mechanisms for restricting access to accounts under Ubuntu 20.04.
Group   Warning Banners for System Accesses   Group contains 1 group and 3 rules
[ref]   Each system should expose as little information about itself as possible.

System banners, which are typically displayed just before a login prompt, give out information about the service or the host's operating system. This might include the distribution name and the system kernel version, and the particular version of a network service. This information can assist intruders in gaining access to the system as it can reveal whether the system is running vulnerable software. Most network services can be configured to limit what information is displayed.

Many organizations implement security policies that require a system banner provide notice of the system's ownership, provide warning to unauthorized users, and remind authorized users of their consent to monitoring.
Group   Implement a GUI Warning Banner   Group contains 2 rules

Rule   Enable GNOME3 Login Warning Banner   [ref]

In the default graphical environment, displaying a login warning banner in the GNOME Display Manager's login screen can be enabled on the login screen by setting banner-message-enable to true.

To enable, add or edit banner-message-enable to /etc/dconf/db/gdm.d/00-security-settings. For example:
[org/gnome/login-screen]
banner-message-enable=true
Once the setting has been added, add a lock to /etc/dconf/db/gdm.d/locks/00-security-settings-lock to prevent user modification. For example:
/org/gnome/login-screen/banner-message-enable
After the settings have been set, run dconf update. The banner text must also be set.
Rationale:
Display of a standardized and approved use notification before granting access to the operating system ensures privacy and security notification verbiage used is consistent with applicable federal laws, Executive Orders, directives, policies, regulations, standards, and guidance.

For U.S. Government systems, system use notifications are required only for access via login interfaces with human users and are not required when such human interfaces do not exist.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_dconf_gnome_banner_enabled
References:
cis-csc1, 12, 15, 16
cobit5DSS05.04, DSS05.10, DSS06.10
cui3.1.9
disaCCI-001387, CCI-001384, CCI-000048, CCI-001386, CCI-001388, CCI-001385
isa-62443-20094.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9
iso27001-2013A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3
nistAC-8(a), AC-8(b), AC-8(c)
nist-csfPR.AC-7
os-srgSRG-OS-000023-GPOS-00006, SRG-OS-000228-GPOS-00088
stigidUBTU-20-010002
cis1.10
stigrefSV-238197r653766_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'gdm3' 2>/dev/null | grep -q installed; then

mkdir -p /etc/dconf/profile
dconf_profile_path=/etc/dconf/profile/user

[[ -s "${dconf_profile_path}" ]] || echo > "${dconf_profile_path}"

if ! grep -Pzq "(?s)^\s*user-db:user.*\n\s*system-db:local" "${dconf_profile_path}"; then
    sed -i --follow-symlinks "1s/^/user-db:user\nsystem-db:local\n/" "${dconf_profile_path}"
fi

# Make sure the corresponding directories exist
mkdir -p /etc/dconf/db/local.d

# Make sure permissions allow regular users to read dconf settings.
# Also define the umask to avoid `dconf update` changing permissions.
chmod -R u=rwX,go=rX /etc/dconf/profile
(umask 0022 && dconf update)
mkdir -p /etc/dconf/profile
dconf_profile_path=/etc/dconf/profile/gdm

[[ -s "${dconf_profile_path}" ]] || echo > "${dconf_profile_path}"

if ! grep -Pzq "(?s)^\s*user-db:user.*\n\s*system-db:gdm" "${dconf_profile_path}"; then
    sed -i --follow-symlinks "1s/^/user-db:user\nsystem-db:gdm\n/" "${dconf_profile_path}"
fi

# Make sure the corresponding directories exist
mkdir -p /etc/dconf/db/gdm.d

# Make sure permissions allow regular users to read dconf settings.
# Also define the umask to avoid `dconf update` changing permissions.
chmod -R u=rwX,go=rX /etc/dconf/profile
(umask 0022 && dconf update)
# Duplicate the setting also in 'greeter.dconf-defaults' for consistency with
# 'dconf_gnome_login_banner_text' and better alignment with STIG V1R1.
if [ -e "/etc/gdm3/greeter.dconf-defaults" ] ; then
    
    LC_ALL=C sed -i "/^\s*banner\-message\-enable/Id" "/etc/gdm3/greeter.dconf-defaults"
else
    touch "/etc/gdm3/greeter.dconf-defaults"
fi
# make sure file has newline at the end
sed -i -e '$a\' "/etc/gdm3/greeter.dconf-defaults"

cp "/etc/gdm3/greeter.dconf-defaults" "/etc/gdm3/greeter.dconf-defaults.bak"
# Insert after the line matching the regex '\[org/gnome/login-screen\]'
line_number="$(LC_ALL=C grep -n "\[org/gnome/login-screen\]" "/etc/gdm3/greeter.dconf-defaults.bak" | LC_ALL=C sed 's/:.*//g')"
if [ -z "$line_number" ]; then
    # There was no match of '\[org/gnome/login-screen\]', insert at
    # the end of the file.
    printf '%s\n' "banner-message-enable=true" >> "/etc/gdm3/greeter.dconf-defaults"
else
    head -n "$(( line_number ))" "/etc/gdm3/greeter.dconf-defaults.bak" > "/etc/gdm3/greeter.dconf-defaults"
    printf '%s\n' "banner-message-enable=true" >> "/etc/gdm3/greeter.dconf-defaults"
    tail -n "+$(( line_number + 1 ))" "/etc/gdm3/greeter.dconf-defaults.bak" >> "/etc/gdm3/greeter.dconf-defaults"
fi
# Clean up after ourselves.
rm "/etc/gdm3/greeter.dconf-defaults.bak"


# Check for setting in any of the DConf db directories
# If files contain ibus or distro, ignore them.
# The assignment assumes that individual filenames don't contain :
readarray -t SETTINGSFILES < <(grep -r "\\[org/gnome/login-screen\\]" "/etc/dconf/db/" \
                                | grep -v 'distro\|ibus\|gdm.d' | cut -d":" -f1)
DCONFFILE="/etc/dconf/db/gdm.d/00-security-settings"
DBDIR="/etc/dconf/db/gdm.d"

mkdir -p "${DBDIR}"

# Comment out the configurations in databases different from the target one
if [ "${#SETTINGSFILES[@]}" -ne 0 ]
then
    if grep -q "^\\s*banner-message-enable\\s*=" "${SETTINGSFILES[@]}"
    then
        
        sed -Ei "s/(^\s*)banner-message-enable(\s*=)/#\1banner-message-enable\2/g" "${SETTINGSFILES[@]}"
    fi
fi

[ ! -z "${DCONFFILE}" ] && echo "" >> "${DCONFFILE}"
if ! grep -q "\\[org/gnome/login-screen\\]" "${DCONFFILE}"
then
    printf '%s\n' "[org/gnome/login-screen]" >> ${DCONFFILE}
fi

escaped_value="$(sed -e 's/\\/\\\\/g' <<< "true")"
if grep -q "^\\s*banner-message-enable\\s*=" "${DCONFFILE}"
then
        sed -i "s/\\s*banner-message-enable\\s*=\\s*.*/banner-message-enable=${escaped_value}/g" "${DCONFFILE}"
    else
        sed -i "\\|\\[org/gnome/login-screen\\]|a\\banner-message-enable=${escaped_value}" "${DCONFFILE}"
fi
# Make sure permissions allow regular users to read dconf settings.
# Also define the umask to avoid `dconf update` changing permissions.
chmod -R u=rwX,go=rX /etc/dconf/db
(umask 0022 && dconf update)
# Check for setting in any of the DConf db directories
LOCKFILES=$(grep -r "^/org/gnome/login-screen/banner-message-enable$" "/etc/dconf/db/" \
            | grep -v 'distro\|ibus\|gdm.d' | grep ":" | cut -d":" -f1)
LOCKSFOLDER="/etc/dconf/db/gdm.d/locks"

mkdir -p "${LOCKSFOLDER}"

# Comment out the configurations in databases different from the target one
if [[ ! -z "${LOCKFILES}" ]]
then
    sed -i -E "s|^/org/gnome/login-screen/banner-message-enable$|#&|" "${LOCKFILES[@]}"
fi

if ! grep -qr "^/org/gnome/login-screen/banner-message-enable$" /etc/dconf/db/gdm.d/
then
    echo "/org/gnome/login-screen/banner-message-enable" >> "/etc/dconf/db/gdm.d/locks/00-security-settings-lock"
fi
# Make sure permissions allow regular users to read dconf settings.
# Also define the umask to avoid `dconf update` changing permissions.
chmod -R u=rwX,go=rX /etc/dconf/db
(umask 0022 && dconf update)

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Rule   Modify the System Login Banner for Remote Connections   [ref]

To configure the system login banner edit /etc/issue.net. Replace the default text with a message compliant with the local site policy or a legal disclaimer. The DoD required text is either:

You are accessing a U.S. Government (USG) Information System (IS) that is provided for USG-authorized use only. By using this IS (which includes any device attached to this IS), you consent to the following conditions:
-The USG routinely intercepts and monitors communications on this IS for purposes including, but not limited to, penetration testing, COMSEC monitoring, network operations and defense, personnel misconduct (PM), law enforcement (LE), and counterintelligence (CI) investigations.
-At any time, the USG may inspect and seize data stored on this IS.
-Communications using, or data stored on, this IS are not private, are subject to routine monitoring, interception, and search, and may be disclosed or used for any USG-authorized purpose.
-This IS includes security measures (e.g., authentication and access controls) to protect USG interests -- not for your personal benefit or privacy.
-Notwithstanding the above, using this IS does not constitute consent to PM, LE or CI investigative searching or monitoring of the content of privileged communications, or work product, related to personal representation or services by attorneys, psychotherapists, or clergy, and their assistants. Such communications and work product are private and confidential. See User Agreement for details.


OR:

I've read & consent to terms in IS user agreem't.
Rationale:
Display of a standardized and approved use notification before granting access to the operating system ensures privacy and security notification verbiage used is consistent with applicable federal laws, Executive Orders, directives, policies, regulations, standards, and guidance.

System use notifications are required only for access via login interfaces with human users and are not required when such human interfaces do not exist.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_banner_etc_issue_net
References:
disaCCI-000048, CCI-001384, CCI-001385, CCI-001386, CCI-001387, CCI-001388
os-srgSRG-OS-000023-GPOS-00006, SRG-OS-000228-GPOS-00088
stigidUBTU-20-010038
cis1.8.1.3
stigrefSV-238214r951471_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

remote_login_banner_text='^(You[\s\n]+are[\s\n]+accessing[\s\n]+a[\s\n]+U\.S\.[\s\n]+Government[\s\n]+\(USG\)[\s\n]+Information[\s\n]+System[\s\n]+\(IS\)[\s\n]+that[\s\n]+is[\s\n]+provided[\s\n]+for[\s\n]+USG\-authorized[\s\n]+use[\s\n]+only\.[\s\n]+By[\s\n]+using[\s\n]+this[\s\n]+IS[\s\n]+\(which[\s\n]+includes[\s\n]+any[\s\n]+device[\s\n]+attached[\s\n]+to[\s\n]+this[\s\n]+IS\),[\s\n]+you[\s\n]+consent[\s\n]+to[\s\n]+the[\s\n]+following[\s\n]+conditions\:(?:[\n]+|(?:\\n)+)\-The[\s\n]+USG[\s\n]+routinely[\s\n]+intercepts[\s\n]+and[\s\n]+monitors[\s\n]+communications[\s\n]+on[\s\n]+this[\s\n]+IS[\s\n]+for[\s\n]+purposes[\s\n]+including,[\s\n]+but[\s\n]+not[\s\n]+limited[\s\n]+to,[\s\n]+penetration[\s\n]+testing,[\s\n]+COMSEC[\s\n]+monitoring,[\s\n]+network[\s\n]+operations[\s\n]+and[\s\n]+defense,[\s\n]+personnel[\s\n]+misconduct[\s\n]+\(PM\),[\s\n]+law[\s\n]+enforcement[\s\n]+\(LE\),[\s\n]+and[\s\n]+counterintelligence[\s\n]+\(CI\)[\s\n]+investigations\.(?:[\n]+|(?:\\n)+)\-At[\s\n]+any[\s\n]+time,[\s\n]+the[\s\n]+USG[\s\n]+may[\s\n]+inspect[\s\n]+and[\s\n]+seize[\s\n]+data[\s\n]+stored[\s\n]+on[\s\n]+this[\s\n]+IS\.(?:[\n]+|(?:\\n)+)\-Communications[\s\n]+using,[\s\n]+or[\s\n]+data[\s\n]+stored[\s\n]+on,[\s\n]+this[\s\n]+IS[\s\n]+are[\s\n]+not[\s\n]+private,[\s\n]+are[\s\n]+subject[\s\n]+to[\s\n]+routine[\s\n]+monitoring,[\s\n]+interception,[\s\n]+and[\s\n]+search,[\s\n]+and[\s\n]+may[\s\n]+be[\s\n]+disclosed[\s\n]+or[\s\n]+used[\s\n]+for[\s\n]+any[\s\n]+USG\-authorized[\s\n]+purpose\.(?:[\n]+|(?:\\n)+)\-This[\s\n]+IS[\s\n]+includes[\s\n]+security[\s\n]+measures[\s\n]+\(e\.g\.,[\s\n]+authentication[\s\n]+and[\s\n]+access[\s\n]+controls\)[\s\n]+to[\s\n]+protect[\s\n]+USG[\s\n]+interests\-\-not[\s\n]+for[\s\n]+your[\s\n]+personal[\s\n]+benefit[\s\n]+or[\s\n]+privacy\.(?:[\n]+|(?:\\n)+)\-Notwithstanding[\s\n]+the[\s\n]+above,[\s\n]+using[\s\n]+this[\s\n]+IS[\s\n]+does[\s\n]+not[\s\n]+constitute[\s\n]+consent[\s\n]+to[\s\n]+PM,[\s\n]+LE[\s\n]+or[\s\n]+CI[\s\n]+investigative[\s\n]+searching[\s\n]+or[\s\n]+monitoring[\s\n]+of[\s\n]+the[\s\n]+content[\s\n]+of[\s\n]+privileged[\s\n]+communications,[\s\n]+or[\s\n]+work[\s\n]+product,[\s\n]+related[\s\n]+to[\s\n]+personal[\s\n]+representation[\s\n]+or[\s\n]+services[\s\n]+by[\s\n]+attorneys,[\s\n]+psychotherapists,[\s\n]+or[\s\n]+clergy,[\s\n]+and[\s\n]+their[\s\n]+assistants\.[\s\n]+Such[\s\n]+communications[\s\n]+and[\s\n]+work[\s\n]+product[\s\n]+are[\s\n]+private[\s\n]+and[\s\n]+confidential\.[\s\n]+See[\s\n]+User[\s\n]+Agreement[\s\n]+for[\s\n]+details\.|I've[\s\n]+read[\s\n]+\&[\s\n]+consent[\s\n]+to[\s\n]+terms[\s\n]+in[\s\n]+IS[\s\n]+user[\s\n]+agreem't\.)$'


# Multiple regexes transform the banner regex into a usable banner
# 0 - Remove anchors around the banner text
remote_login_banner_text=$(echo "$remote_login_banner_text" | sed 's/^\^\(.*\)\$$/\1/g')
# 1 - Keep only the first banners if there are multiple
#    (dod_banners contains the long and short banner)
remote_login_banner_text=$(echo "$remote_login_banner_text" | sed 's/^(\(.*\.\)|.*)$/\1/g')
# 2 - Add spaces ' '. (Transforms regex for "space or newline" into a " ")
remote_login_banner_text=$(echo "$remote_login_banner_text" | sed 's/\[\\s\\n\]+/ /g')
# 3 - Adds newlines. (Transforms "(?:\[\\n\]+|(?:\\n)+)" into "\n")
remote_login_banner_text=$(echo "$remote_login_banner_text" | sed 's/(?:\[\\n\]+|(?:\\\\n)+)/\n/g')
# 4 - Remove any leftover backslash. (From any parethesis in the banner, for example).
remote_login_banner_text=$(echo "$remote_login_banner_text" | sed 's/\\//g')
formatted=$(echo "$remote_login_banner_text" | fold -sw 80)

cat <<EOF >/etc/issue.net
$formatted
EOF

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:medium
Reboot:false
Strategy:unknown
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010038
  - banner_etc_issue_net
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - unknown_strategy
- name: XCCDF Value remote_login_banner_text # promote to variable
  set_fact:
    remote_login_banner_text: !!str ^(You[\s\n]+are[\s\n]+accessing[\s\n]+a[\s\n]+U\.S\.[\s\n]+Government[\s\n]+\(USG\)[\s\n]+Information[\s\n]+System[\s\n]+\(IS\)[\s\n]+that[\s\n]+is[\s\n]+provided[\s\n]+for[\s\n]+USG\-authorized[\s\n]+use[\s\n]+only\.[\s\n]+By[\s\n]+using[\s\n]+this[\s\n]+IS[\s\n]+\(which[\s\n]+includes[\s\n]+any[\s\n]+device[\s\n]+attached[\s\n]+to[\s\n]+this[\s\n]+IS\),[\s\n]+you[\s\n]+consent[\s\n]+to[\s\n]+the[\s\n]+following[\s\n]+conditions\:(?:[\n]+|(?:\\n)+)\-The[\s\n]+USG[\s\n]+routinely[\s\n]+intercepts[\s\n]+and[\s\n]+monitors[\s\n]+communications[\s\n]+on[\s\n]+this[\s\n]+IS[\s\n]+for[\s\n]+purposes[\s\n]+including,[\s\n]+but[\s\n]+not[\s\n]+limited[\s\n]+to,[\s\n]+penetration[\s\n]+testing,[\s\n]+COMSEC[\s\n]+monitoring,[\s\n]+network[\s\n]+operations[\s\n]+and[\s\n]+defense,[\s\n]+personnel[\s\n]+misconduct[\s\n]+\(PM\),[\s\n]+law[\s\n]+enforcement[\s\n]+\(LE\),[\s\n]+and[\s\n]+counterintelligence[\s\n]+\(CI\)[\s\n]+investigations\.(?:[\n]+|(?:\\n)+)\-At[\s\n]+any[\s\n]+time,[\s\n]+the[\s\n]+USG[\s\n]+may[\s\n]+inspect[\s\n]+and[\s\n]+seize[\s\n]+data[\s\n]+stored[\s\n]+on[\s\n]+this[\s\n]+IS\.(?:[\n]+|(?:\\n)+)\-Communications[\s\n]+using,[\s\n]+or[\s\n]+data[\s\n]+stored[\s\n]+on,[\s\n]+this[\s\n]+IS[\s\n]+are[\s\n]+not[\s\n]+private,[\s\n]+are[\s\n]+subject[\s\n]+to[\s\n]+routine[\s\n]+monitoring,[\s\n]+interception,[\s\n]+and[\s\n]+search,[\s\n]+and[\s\n]+may[\s\n]+be[\s\n]+disclosed[\s\n]+or[\s\n]+used[\s\n]+for[\s\n]+any[\s\n]+USG\-authorized[\s\n]+purpose\.(?:[\n]+|(?:\\n)+)\-This[\s\n]+IS[\s\n]+includes[\s\n]+security[\s\n]+measures[\s\n]+\(e\.g\.,[\s\n]+authentication[\s\n]+and[\s\n]+access[\s\n]+controls\)[\s\n]+to[\s\n]+protect[\s\n]+USG[\s\n]+interests\-\-not[\s\n]+for[\s\n]+your[\s\n]+personal[\s\n]+benefit[\s\n]+or[\s\n]+privacy\.(?:[\n]+|(?:\\n)+)\-Notwithstanding[\s\n]+the[\s\n]+above,[\s\n]+using[\s\n]+this[\s\n]+IS[\s\n]+does[\s\n]+not[\s\n]+constitute[\s\n]+consent[\s\n]+to[\s\n]+PM,[\s\n]+LE[\s\n]+or[\s\n]+CI[\s\n]+investigative[\s\n]+searching[\s\n]+or[\s\n]+monitoring[\s\n]+of[\s\n]+the[\s\n]+content[\s\n]+of[\s\n]+privileged[\s\n]+communications,[\s\n]+or[\s\n]+work[\s\n]+product,[\s\n]+related[\s\n]+to[\s\n]+personal[\s\n]+representation[\s\n]+or[\s\n]+services[\s\n]+by[\s\n]+attorneys,[\s\n]+psychotherapists,[\s\n]+or[\s\n]+clergy,[\s\n]+and[\s\n]+their[\s\n]+assistants\.[\s\n]+Such[\s\n]+communications[\s\n]+and[\s\n]+work[\s\n]+product[\s\n]+are[\s\n]+private[\s\n]+and[\s\n]+confidential\.[\s\n]+See[\s\n]+User[\s\n]+Agreement[\s\n]+for[\s\n]+details\.|I've[\s\n]+read[\s\n]+\&[\s\n]+consent[\s\n]+to[\s\n]+terms[\s\n]+in[\s\n]+IS[\s\n]+user[\s\n]+agreem't\.)$
  tags:
    - always

- name: Modify the System Login Banner for Remote Connections - ensure correct banner
  copy:
    dest: /etc/issue.net
    content: '{{ remote_login_banner_text | regex_replace("^\^(.*)\$$", "\1") | regex_replace("^\((.*\.)\|.*\)$",
      "\1") | regex_replace("\[\\s\\n\]\+"," ") | regex_replace("\(\?:\[\\n\]\+\|\(\?:\\\\n\)\+\)",
      "\n") | regex_replace("\\", "") | wordwrap() }}'
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010038
  - banner_etc_issue_net
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - unknown_strategy
Group   Protect Accounts by Configuring PAM   Group contains 4 groups and 19 rules
[ref]   PAM, or Pluggable Authentication Modules, is a system which implements modular authentication for Linux programs. PAM provides a flexible and configurable architecture for authentication, and it should be configured to minimize exposure to unnecessary risk. This section contains guidance on how to accomplish that.

PAM is implemented as a set of shared objects which are loaded and invoked whenever an application wishes to authenticate a user. Typically, the application must be running as root in order to take advantage of PAM, because PAM's modules often need to be able to access sensitive stores of account information, such as /etc/shadow. Traditional privileged network listeners (e.g. sshd) or SUID programs (e.g. sudo) already meet this requirement. An SUID root application, userhelper, is provided so that programs which are not SUID or privileged themselves can still take advantage of PAM.

PAM looks in the directory /etc/pam.d for application-specific configuration information. For instance, if the program login attempts to authenticate a user, then PAM's libraries follow the instructions in the file /etc/pam.d/login to determine what actions should be taken.

One very important file in /etc/pam.d is /etc/pam.d/system-auth. This file, which is included by many other PAM configuration files, defines 'default' system authentication measures. Modifying this file is a good way to make far-reaching authentication changes, for instance when implementing a centralized authentication service.
Warning:  Be careful when making changes to PAM's configuration files. The syntax for these files is complex, and modifications can have unexpected consequences. The default configurations shipped with applications should be sufficient for most users.
Warning:  Running authconfig or system-config-authentication will re-write the PAM configuration files, destroying any manually made changes and replacing them with a series of system defaults. One reference to the configuration file syntax can be found at https://fossies.org/linux/Linux-PAM-docs/doc/sag/Linux-PAM_SAG.pdf.
Group   Set Lockouts for Failed Password Attempts   Group contains 7 rules
[ref]   The pam_faillock PAM module provides the capability to lock out user accounts after a number of failed login attempts. Its documentation is available in /usr/share/doc/pam-VERSION/txts/README.pam_faillock.

Warning:  Locking out user accounts presents the risk of a denial-of-service attack. The lockout policy must weigh whether the risk of such a denial-of-service attack outweighs the benefits of thwarting password guessing attacks.

Rule   Limit Password Reuse   [ref]

Do not allow users to reuse recent passwords. This can be accomplished by using the remember option for the pam_unix or pam_pwhistory PAM modules.
Warning:  If the system relies on authselect tool to manage PAM settings, the remediation will also use authselect tool. However, if any manual modification was made in PAM files, the authselect integrity check will fail and the remediation will be aborted in order to preserve intentional changes. In this case, an informative message will be shown in the remediation report.
Warning:  Newer versions of authselect contain an authselect feature to easily and properly enable pam_pwhistory.so module. If this feature is not yet available in your system, an authselect custom profile must be used to avoid integrity issues in PAM files.
Rationale:
Preventing re-use of previous passwords helps ensure that a compromised password is not re-used by a user.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_password_pam_unix_remember
References:
cis-csc1, 12, 15, 16, 5
cjis5.6.2.1.1
cobit5DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
cui3.5.8
disaCCI-000200
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1
iso27001-2013A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
nistIA-5(f), IA-5(1)(e)
nist-csfPR.AC-1, PR.AC-6, PR.AC-7
pcidssReq-8.2.5
os-srgSRG-OS-000077-GPOS-00045
stigidUBTU-20-010070
anssiR31
pcidss48.3.7, 8.3
stigrefSV-238234r832945_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_password_pam_unix_remember='5'



config_file="/usr/share/pam-configs/cac_unix"



conf_name=cac_unix
conf_path="/usr/share/pam-configs"

if [ ! -f "$conf_path"/"$conf_name" ]; then
    if [ -f "$conf_path"/unix ]; then
        if grep -q "$(md5sum "$conf_path"/unix | cut -d ' ' -f 1)" /var/lib/dpkg/info/libpam-runtime.md5sums;then
            cp "$conf_path"/unix "$conf_path"/"$conf_name"
            sed -i '/Default: yes/a Priority: 257\
Conflicts: unix' "$conf_path"/"$conf_name"
            DEBIAN_FRONTEND=noninteractive pam-auth-update
        else
            echo "Not applicable - checksum of $conf_path/unix does not match the original." >&2
        fi
    else
        echo "Not applicable - $conf_path/unix does not exist" >&2
    fi
fi
sed -i -E '/^Password:/,/^[^[:space:]]/ {
    /pam_unix\.so/ {
        s/\s*remember=[^[:space:]]*//g
        s/$/ remember='"$var_password_pam_unix_remember"'/g
    }
}' "$config_file"

sed -i -E '/^Password-Initial:/,/^[^[:space:]]/ {
    /pam_unix\.so/ {
        s/\s*remember=[^[:space:]]*//g
        s/$/ remember='"$var_password_pam_unix_remember"'/g
    }
}' "$config_file"

DEBIAN_FRONTEND=noninteractive pam-auth-update

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:medium
Reboot:false
Strategy:configure
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.6.2.1.1
  - DISA-STIG-UBTU-20-010070
  - NIST-800-171-3.5.8
  - NIST-800-53-IA-5(1)(e)
  - NIST-800-53-IA-5(f)
  - PCI-DSS-Req-8.2.5
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.7
  - accounts_password_pam_unix_remember
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
- name: XCCDF Value var_password_pam_unix_remember # promote to variable
  set_fact:
    var_password_pam_unix_remember: !!str 5
  tags:
    - always

- name: Limit Password Reuse - Check if the required PAM module option is present
    in /etc/pam.d/common-password
  ansible.builtin.lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^\s*password\s+\[success=[A-Za-z0-9].*\]\s+pam_unix.so\s*.*\sremember\b
    state: absent
  check_mode: true
  changed_when: false
  register: result_pam_module_remember_option_present
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - CJIS-5.6.2.1.1
  - DISA-STIG-UBTU-20-010070
  - NIST-800-171-3.5.8
  - NIST-800-53-IA-5(1)(e)
  - NIST-800-53-IA-5(f)
  - PCI-DSS-Req-8.2.5
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.7
  - accounts_password_pam_unix_remember
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed

- name: Limit Password Reuse - Ensure the "remember" PAM option for "pam_unix.so"
    is included in /etc/pam.d/common-password
  ansible.builtin.lineinfile:
    path: /etc/pam.d/common-password
    backrefs: true
    regexp: ^(\s*password\s+\[success=[A-Za-z0-9].*\]\s+pam_unix.so.*)
    line: \1 remember={{ var_password_pam_unix_remember }}
    state: present
  register: result_pam_remember_add
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - result_pam_module_remember_option_present.found == 0
  tags:
  - CJIS-5.6.2.1.1
  - DISA-STIG-UBTU-20-010070
  - NIST-800-171-3.5.8
  - NIST-800-53-IA-5(1)(e)
  - NIST-800-53-IA-5(f)
  - PCI-DSS-Req-8.2.5
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.7
  - accounts_password_pam_unix_remember
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed

- name: Limit Password Reuse - Ensure the required value for "remember" PAM option
    from "pam_unix.so" in /etc/pam.d/common-password
  ansible.builtin.lineinfile:
    path: /etc/pam.d/common-password
    backrefs: true
    regexp: ^(\s*password\s+\[success=[A-Za-z0-9].*\]\s+pam_unix.so\s+.*)(remember)=[0-9a-zA-Z]+\s*(.*)
    line: \1\2={{ var_password_pam_unix_remember }} \3
  register: result_pam_remember_edit
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - result_pam_module_remember_option_present.found > 0
  tags:
  - CJIS-5.6.2.1.1
  - DISA-STIG-UBTU-20-010070
  - NIST-800-171-3.5.8
  - NIST-800-53-IA-5(1)(e)
  - NIST-800-53-IA-5(f)
  - PCI-DSS-Req-8.2.5
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.7
  - accounts_password_pam_unix_remember
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed

Rule   Enforce Delay After Failed Logon Attempts   [ref]

To configure the system to introduce a delay after failed logon attempts, add or correct the pam_faildelay settings in /etc/pam.d/common-auth to make sure its delay parameter is at least 4000000 or greater. For example:
auth required pam_faildelay.so delay=4000000
         
Rationale:
Limiting the number of logon attempts over a certain time interval reduces the chances that an unauthorized user may gain access to an account.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_passwords_pam_faildelay_delay
References:
disaCCI-000366
os-srgSRG-OS-000480-GPOS-00226
stigidUBTU-20-010075
stigrefSV-238237r653886_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_password_pam_delay='4000000'




if ! grep -qP "^\s*auth\s+required\s+pam_faildelay.so\s*.*" "/etc/pam.d/common-auth"; then
    # Line matching group + control + module was not found. Check group + module.
    if [ "$(grep -cP '^\s*auth\s+.*\s+pam_faildelay.so\s*' "/etc/pam.d/common-auth")" -eq 1 ]; then
        # The control is updated only if one single line matches.
        sed -i -E --follow-symlinks "s/^(\s*auth\s+).*(\bpam_faildelay.so.*)/\1required \2/" "/etc/pam.d/common-auth"
    else
        sed -i --follow-symlinks "1i auth     required    pam_faildelay.so" "/etc/pam.d/common-auth"
    fi
fi
# Check the option
if ! grep -qP "^\s*auth\s+required\s+pam_faildelay.so\s*.*\sdelay\b" "/etc/pam.d/common-auth"; then
    sed -i -E --follow-symlinks "/\s*auth\s+required\s+pam_faildelay.so.*/ s/$/ delay=$var_password_pam_delay/" "/etc/pam.d/common-auth"
else
    sed -i -E --follow-symlinks "s/(\s*auth\s+required\s+pam_faildelay.so\s+.*)(delay=)[[:alnum:]]+\s*(.*)/\1\2$var_password_pam_delay \3/" "/etc/pam.d/common-auth"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Rule   Account Lockouts Must Be Logged   [ref]

PAM faillock locks an account due to excessive password failures, this event must be logged.
Rationale:
Without auditing of these events it may be harder or impossible to identify what an attacker did after an attack.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_passwords_pam_faillock_audit
References:
disaCCI-000044
nistAC-7 (a)
os-srgSRG-OS-000021-GPOS-00005
stigidUBTU-20-010072
stigrefSV-238235r853414_rule


if [ -f /usr/bin/authselect ]; then
    if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
authselect enable-feature with-faillock

authselect apply-changes -b
else
    
conf_name=cac_faillock

if [ ! -f /usr/share/pam-configs/"$conf_name" ]; then
    cat << EOF > /usr/share/pam-configs/"$conf_name"
Name: Enable pam_faillock to deny access
Default: yes
Conflicts: faillock
Priority: 0
Auth-Type: Primary
Auth:
    [default=die]                   pam_faillock.so authfail
EOF
fi

if [ ! -f /usr/share/pam-configs/"$conf_name"_notify ]; then
    cat << EOF > /usr/share/pam-configs/"$conf_name"_notify
Name: Notify of failed login attempts and reset count upon success
Default: yes
Conflicts: faillock_notify
Priority: 1025
Auth-Type: Primary
Auth:
    requisite                       pam_faillock.so preauth
Account-Type: Primary
Account:
    required                        pam_faillock.so
EOF
fi

DEBIAN_FRONTEND=noninteractive pam-auth-update


fi

AUTH_FILES=("/etc/pam.d/common-auth")
SKIP_FAILLOCK_CHECK=true

FAILLOCK_CONF="/etc/security/faillock.conf"
if [ -f $FAILLOCK_CONF ] || [ "$SKIP_FAILLOCK_CHECK" = "true" ]; then
    regex="^\s*audit"
    line="audit"
    if ! grep -q $regex $FAILLOCK_CONF; then
        echo $line >> $FAILLOCK_CONF
    fi
    
else
    for pam_file in "${AUTH_FILES[@]}"
    do
        if ! grep -qE '^\s*auth.*pam_faillock\.so (preauth|authfail).*audit' "$pam_file"; then
            sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*preauth.*silent.*/ s/$/ audit/' "$pam_file"
        fi
    done
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Account Lockouts Must Be Logged - Check if system relies on authselect tool
  ansible.builtin.stat:
    path: /usr/bin/authselect
  register: result_authselect_present
  tags:
  - DISA-STIG-UBTU-20-010072
  - NIST-800-53-AC-7 (a)
  - accounts_passwords_pam_faillock_audit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Account Lockouts Must Be Logged - Remediation where authselect tool is present
  block:

  - name: Account Lockouts Must Be Logged - Check integrity of authselect current
      profile
    ansible.builtin.command:
      cmd: authselect check
    register: result_authselect_check_cmd
    changed_when: false
    failed_when: false

  - name: Account Lockouts Must Be Logged - Informative message based on the authselect
      integrity check result
    ansible.builtin.assert:
      that:
      - result_authselect_check_cmd.rc == 0
      fail_msg:
      - authselect integrity check failed. Remediation aborted!
      - This remediation could not be applied because an authselect profile was not
        selected or the selected profile is not intact.
      - It is not recommended to manually edit the PAM files when authselect tool
        is available.
      - In cases where the default authselect profile does not cover a specific demand,
        a custom authselect profile is recommended.
      success_msg:
      - authselect integrity check passed

  - name: Account Lockouts Must Be Logged - Get authselect current features
    ansible.builtin.shell:
      cmd: authselect current | tail -n+3 | awk '{ print $2 }'
    register: result_authselect_features
    changed_when: false
    when:
    - result_authselect_check_cmd is success

  - name: Account Lockouts Must Be Logged - Ensure "with-faillock" feature is enabled
      using authselect tool
    ansible.builtin.command:
      cmd: authselect enable-feature with-faillock
    register: result_authselect_enable_feature_cmd
    when:
    - result_authselect_check_cmd is success
    - result_authselect_features.stdout is not search("with-faillock")

  - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
    ansible.builtin.command:
      cmd: authselect apply-changes -b
    when:
    - result_authselect_enable_feature_cmd is not skipped
    - result_authselect_enable_feature_cmd is success
  when: result_authselect_present.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010072
  - NIST-800-53-AC-7 (a)
  - accounts_passwords_pam_faillock_audit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Account Lockouts Must Be Logged - Remediation where authselect tool is not
    present
  block:

  - name: Account Lockouts Must Be Logged - Check if pam_faillock.so is already enabled
    ansible.builtin.lineinfile:
      path: /etc/pam.d/system-auth
      regexp: .*auth.*pam_faillock\.so (preauth|authfail)
      state: absent
    check_mode: true
    changed_when: false
    register: result_pam_faillock_is_enabled

  - name: Account Lockouts Must Be Logged - Enable pam_faillock.so preauth editing
      PAM files
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      line: auth        required      pam_faillock.so preauth
      insertbefore: ^auth.*sufficient.*pam_unix\.so.*
      state: present
    loop:
    - /etc/pam.d/system-auth
    - /etc/pam.d/password-auth
    when:
    - result_pam_faillock_is_enabled.found == 0

  - name: Account Lockouts Must Be Logged - Enable pam_faillock.so authfail editing
      PAM files
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      line: auth        required      pam_faillock.so authfail
      insertbefore: ^auth.*required.*pam_deny\.so.*
      state: present
    loop:
    - /etc/pam.d/system-auth
    - /etc/pam.d/password-auth
    when:
    - result_pam_faillock_is_enabled.found == 0

  - name: Account Lockouts Must Be Logged - Enable pam_faillock.so account section
      editing PAM files
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      line: account     required      pam_faillock.so
      insertbefore: ^account.*required.*pam_unix\.so.*
      state: present
    loop:
    - /etc/pam.d/system-auth
    - /etc/pam.d/password-auth
    when:
    - result_pam_faillock_is_enabled.found == 0
  when: not result_authselect_present.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010072
  - NIST-800-53-AC-7 (a)
  - accounts_passwords_pam_faillock_audit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Account Lockouts Must Be Logged - Check the presence of /etc/security/faillock.conf
    file
  ansible.builtin.stat:
    path: /etc/security/faillock.conf
  register: result_faillock_conf_check
  tags:
  - DISA-STIG-UBTU-20-010072
  - NIST-800-53-AC-7 (a)
  - accounts_passwords_pam_faillock_audit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Account Lockouts Must Be Logged - Ensure the pam_faillock.so audit parameter
    in /etc/security/faillock.conf
  ansible.builtin.lineinfile:
    path: /etc/security/faillock.conf
    regexp: ^\s*audit
    line: audit
    state: present
  when: result_faillock_conf_check.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010072
  - NIST-800-53-AC-7 (a)
  - accounts_passwords_pam_faillock_audit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Account Lockouts Must Be Logged - Ensure the pam_faillock.so audit parameter
    not in PAM files
  block:

  - name: Account Lockouts Must Be Logged - Check if /etc/pam.d/system-auth file is
      present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_file_present

  - name: Account Lockouts Must Be Logged - Check the proper remediation for the system
    block:

    - name: Account Lockouts Must Be Logged - Define the PAM file to be edited as
        a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Account Lockouts Must Be Logged - Check if system relies on authselect
        tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Account Lockouts Must Be Logged - Ensure authselect custom profile is
        used if authselect is present
      block:

      - name: Account Lockouts Must Be Logged - Check integrity of authselect current
          profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        failed_when: false

      - name: Account Lockouts Must Be Logged - Informative message based on the authselect
          integrity check result
        ansible.builtin.assert:
          that:
          - result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Account Lockouts Must Be Logged - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Account Lockouts Must Be Logged - Define the current authselect profile
          as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Account Lockouts Must Be Logged - Define the new authselect custom profile
          as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Account Lockouts Must Be Logged - Get authselect current features to
          also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Account Lockouts Must Be Logged - Check if any custom profile with the
          same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - authselect_current_profile is not match("custom/")

      - name: Account Lockouts Must Be Logged - Create an authselect custom profile
          based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("custom/")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Account Lockouts Must Be Logged - Ensure the authselect custom profile
          is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Account Lockouts Must Be Logged - Restore the authselect features in
          the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Account Lockouts Must Be Logged - Change the PAM file to be edited according
          to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
      when:
      - result_authselect_present.stat.exists

    - name: Account Lockouts Must Be Logged - Define a fact for control already filtered
        in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Account Lockouts Must Be Logged - Ensure the "audit" option from "pam_faillock.so"
        is not present in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*auth.*pam_faillock.so.*)\baudit\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal

    - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - result_pam_file_present.stat.exists

  - name: Account Lockouts Must Be Logged - Check if /etc/pam.d/password-auth file
      is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_file_present

  - name: Account Lockouts Must Be Logged - Check the proper remediation for the system
    block:

    - name: Account Lockouts Must Be Logged - Define the PAM file to be edited as
        a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Account Lockouts Must Be Logged - Check if system relies on authselect
        tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Account Lockouts Must Be Logged - Ensure authselect custom profile is
        used if authselect is present
      block:

      - name: Account Lockouts Must Be Logged - Check integrity of authselect current
          profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        failed_when: false

      - name: Account Lockouts Must Be Logged - Informative message based on the authselect
          integrity check result
        ansible.builtin.assert:
          that:
          - result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Account Lockouts Must Be Logged - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Account Lockouts Must Be Logged - Define the current authselect profile
          as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Account Lockouts Must Be Logged - Define the new authselect custom profile
          as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Account Lockouts Must Be Logged - Get authselect current features to
          also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Account Lockouts Must Be Logged - Check if any custom profile with the
          same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - authselect_current_profile is not match("custom/")

      - name: Account Lockouts Must Be Logged - Create an authselect custom profile
          based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("custom/")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Account Lockouts Must Be Logged - Ensure the authselect custom profile
          is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Account Lockouts Must Be Logged - Restore the authselect features in
          the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Account Lockouts Must Be Logged - Change the PAM file to be edited according
          to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
      when:
      - result_authselect_present.stat.exists

    - name: Account Lockouts Must Be Logged - Define a fact for control already filtered
        in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Account Lockouts Must Be Logged - Ensure the "audit" option from "pam_faillock.so"
        is not present in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*auth.*pam_faillock.so.*)\baudit\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal

    - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - result_pam_file_present.stat.exists
  when: result_faillock_conf_check.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010072
  - NIST-800-53-AC-7 (a)
  - accounts_passwords_pam_faillock_audit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Account Lockouts Must Be Logged - Ensure the pam_faillock.so audit parameter
    in PAM files
  block:

  - name: Account Lockouts Must Be Logged - Check if pam_faillock.so audit parameter
      is already enabled in pam files
    ansible.builtin.lineinfile:
      path: /etc/pam.d/system-auth
      regexp: .*auth.*pam_faillock\.so (preauth|authfail).*audit
      state: absent
    check_mode: true
    changed_when: false
    register: result_pam_faillock_audit_parameter_is_present

  - name: Account Lockouts Must Be Logged - Ensure the inclusion of pam_faillock.so
      preauth audit parameter in auth section
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      backrefs: true
      regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)
      line: \1required\3 audit
      state: present
    loop:
    - /etc/pam.d/system-auth
    - /etc/pam.d/password-auth
    when:
    - result_pam_faillock_audit_parameter_is_present.found == 0
  when: not result_faillock_conf_check.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010072
  - NIST-800-53-AC-7 (a)
  - accounts_passwords_pam_faillock_audit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

Rule   Lock Accounts After Failed Password Attempts   [ref]

This rule configures the system to lock out accounts after a number of incorrect login attempts using pam_faillock.so. pam_faillock.so module requires multiple entries in pam files. These entries must be carefully defined to work as expected. Ensure that the file /etc/security/faillock.conf contains the following entry: deny = <count> Where count should be less than or equal to 3 and greater than 0.
Warning:  If the system relies on authselect tool to manage PAM settings, the remediation will also use authselect tool. However, if any manual modification was made in PAM files, the authselect integrity check will fail and the remediation will be aborted in order to preserve intentional changes. In this case, an informative message will be shown in the remediation report. If the system supports the /etc/security/faillock.conf file, the pam_faillock parameters should be defined in faillock.conf file.
Rationale:
By limiting the number of failed logon attempts, the risk of unauthorized system access via user password guessing, also known as brute-forcing, is reduced. Limits are imposed by locking the account.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_passwords_pam_faillock_deny
References:
cis-csc1, 12, 15, 16
cjis5.5.3
cobit5DSS05.04, DSS05.10, DSS06.10
cui3.1.8
disaCCI-000044, CCI-002238
isa-62443-20094.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9
ism0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561
iso27001-2013A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3
nistCM-6(a), AC-7(a)
nist-csfPR.AC-7
osppFIA_AFL.1
pcidssReq-8.1.6
os-srgSRG-OS-000329-GPOS-00128, SRG-OS-000021-GPOS-00005
stigidUBTU-20-010072
anssiR31
pcidss48.3.4, 8.3
stigrefSV-238235r853414_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_accounts_passwords_pam_faillock_deny='3'


if [ -f /usr/bin/authselect ]; then
    if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
authselect enable-feature with-faillock

authselect apply-changes -b
else
    
conf_name=cac_faillock

if [ ! -f /usr/share/pam-configs/"$conf_name" ]; then
    cat << EOF > /usr/share/pam-configs/"$conf_name"
Name: Enable pam_faillock to deny access
Default: yes
Conflicts: faillock
Priority: 0
Auth-Type: Primary
Auth:
    [default=die]                   pam_faillock.so authfail
EOF
fi

if [ ! -f /usr/share/pam-configs/"$conf_name"_notify ]; then
    cat << EOF > /usr/share/pam-configs/"$conf_name"_notify
Name: Notify of failed login attempts and reset count upon success
Default: yes
Conflicts: faillock_notify
Priority: 1025
Auth-Type: Primary
Auth:
    requisite                       pam_faillock.so preauth
Account-Type: Primary
Account:
    required                        pam_faillock.so
EOF
fi

DEBIAN_FRONTEND=noninteractive pam-auth-update


fi

AUTH_FILES=("/etc/pam.d/common-auth")
SKIP_FAILLOCK_CHECK=true

FAILLOCK_CONF="/etc/security/faillock.conf"
if [ -f $FAILLOCK_CONF ] || [ "$SKIP_FAILLOCK_CHECK" = "true" ]; then
    regex="^\s*deny\s*="
    line="deny = $var_accounts_passwords_pam_faillock_deny"
    if ! grep -q $regex $FAILLOCK_CONF; then
        echo $line >> $FAILLOCK_CONF
    else
        sed -i --follow-symlinks 's|^\s*\(deny\s*=\s*\)\(\S\+\)|\1'"$var_accounts_passwords_pam_faillock_deny"'|g' $FAILLOCK_CONF
    fi
    
else
    for pam_file in "${AUTH_FILES[@]}"
    do
        if ! grep -qE '^\s*auth.*pam_faillock\.so (preauth|authfail).*deny' "$pam_file"; then
            sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*preauth.*silent.*/ s/$/ deny='"$var_accounts_passwords_pam_faillock_deny"'/' "$pam_file"
            sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*authfail.*/ s/$/ deny='"$var_accounts_passwords_pam_faillock_deny"'/' "$pam_file"
        else
            sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock\.so.*preauth.*silent.*\)\('"deny"'=\)[0-9]\+\(.*\)/\1\2'"$var_accounts_passwords_pam_faillock_deny"'\3/' "$pam_file"
            sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock\.so.*authfail.*\)\('"deny"'=\)[0-9]\+\(.*\)/\1\2'"$var_accounts_passwords_pam_faillock_deny"'\3/' "$pam_file"
        fi
    done
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Rule   Set Interval For Counting Failed Password Attempts   [ref]

Utilizing pam_faillock.so, the fail_interval directive configures the system to lock out an account after a number of incorrect login attempts within a specified time period. Ensure that the file /etc/security/faillock.conf contains the following entry: fail_interval = <interval-in-seconds> where interval-in-seconds is 900 or greater.
Warning:  If the system relies on authselect tool to manage PAM settings, the remediation will also use authselect tool. However, if any manual modification was made in PAM files, the authselect integrity check will fail and the remediation will be aborted in order to preserve intentional changes. In this case, an informative message will be shown in the remediation report. If the system supports the /etc/security/faillock.conf file, the pam_faillock parameters should be defined in faillock.conf file.
Rationale:
By limiting the number of failed logon attempts the risk of unauthorized system access via user password guessing, otherwise known as brute-forcing, is reduced. Limits are imposed by locking the account.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_passwords_pam_faillock_interval
References:
cis-csc1, 12, 15, 16
cobit5DSS05.04, DSS05.10, DSS06.10
disaCCI-000044, CCI-002238
isa-62443-20094.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9
ism0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561
iso27001-2013A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3
nistCM-6(a), AC-7(a)
nist-csfPR.AC-7
osppFIA_AFL.1
os-srgSRG-OS-000329-GPOS-00128, SRG-OS-000021-GPOS-00005
stigidUBTU-20-010072
anssiR31
stigrefSV-238235r853414_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_accounts_passwords_pam_faillock_fail_interval='900'


if [ -f /usr/bin/authselect ]; then
    if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
authselect enable-feature with-faillock

authselect apply-changes -b
else
    
conf_name=cac_faillock

if [ ! -f /usr/share/pam-configs/"$conf_name" ]; then
    cat << EOF > /usr/share/pam-configs/"$conf_name"
Name: Enable pam_faillock to deny access
Default: yes
Conflicts: faillock
Priority: 0
Auth-Type: Primary
Auth:
    [default=die]                   pam_faillock.so authfail
EOF
fi

if [ ! -f /usr/share/pam-configs/"$conf_name"_notify ]; then
    cat << EOF > /usr/share/pam-configs/"$conf_name"_notify
Name: Notify of failed login attempts and reset count upon success
Default: yes
Conflicts: faillock_notify
Priority: 1025
Auth-Type: Primary
Auth:
    requisite                       pam_faillock.so preauth
Account-Type: Primary
Account:
    required                        pam_faillock.so
EOF
fi

DEBIAN_FRONTEND=noninteractive pam-auth-update


fi

AUTH_FILES=("/etc/pam.d/common-auth")
SKIP_FAILLOCK_CHECK=true

FAILLOCK_CONF="/etc/security/faillock.conf"
if [ -f $FAILLOCK_CONF ] || [ "$SKIP_FAILLOCK_CHECK" = "true" ]; then
    regex="^\s*fail_interval\s*="
    line="fail_interval = $var_accounts_passwords_pam_faillock_fail_interval"
    if ! grep -q $regex $FAILLOCK_CONF; then
        echo $line >> $FAILLOCK_CONF
    else
        sed -i --follow-symlinks 's|^\s*\(fail_interval\s*=\s*\)\(\S\+\)|\1'"$var_accounts_passwords_pam_faillock_fail_interval"'|g' $FAILLOCK_CONF
    fi
    
else
    for pam_file in "${AUTH_FILES[@]}"
    do
        if ! grep -qE '^\s*auth.*pam_faillock\.so (preauth|authfail).*fail_interval' "$pam_file"; then
            sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*preauth.*silent.*/ s/$/ fail_interval='"$var_accounts_passwords_pam_faillock_fail_interval"'/' "$pam_file"
            sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*authfail.*/ s/$/ fail_interval='"$var_accounts_passwords_pam_faillock_fail_interval"'/' "$pam_file"
        else
            sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock\.so.*preauth.*silent.*\)\('"fail_interval"'=\)[0-9]\+\(.*\)/\1\2'"$var_accounts_passwords_pam_faillock_fail_interval"'\3/' "$pam_file"
            sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock\.so.*authfail.*\)\('"fail_interval"'=\)[0-9]\+\(.*\)/\1\2'"$var_accounts_passwords_pam_faillock_fail_interval"'\3/' "$pam_file"
        fi
    done
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Rule   Do Not Show System Messages When Unsuccessful Logon Attempts Occur   [ref]

This rule ensures the system prevents informative messages from being presented to the user pertaining to logon information after a number of incorrect login attempts using pam_faillock.so. pam_faillock.so module requires multiple entries in pam files. These entries must be carefully defined to work as expected. In order to avoid errors when manually editing these files, it is recommended to use the appropriate tools, such as authselect or authconfig, depending on the OS version.
Warning:  If the system relies on authselect tool to manage PAM settings, the remediation will also use authselect tool. However, if any manual modification was made in PAM files, the authselect integrity check will fail and the remediation will be aborted in order to preserve intentional changes. In this case, an informative message will be shown in the remediation report. If the system supports the /etc/security/faillock.conf file, the pam_faillock parameters should be defined in faillock.conf file.
Rationale:
The pam_faillock module without the silent option will leak information about the existence or non-existence of a user account in the system because the failures are not recorded for unknown users. The message about the user account being locked is never displayed for non-existing user accounts allowing the adversary to infer that a particular account exists or not on the system.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_passwords_pam_faillock_silent
References:
disaCCI-002238, CCI-000044
os-srgSRG-OS-000329-GPOS-00128, SRG-OS-000021-GPOS-00005
stigidUBTU-20-010072
stigrefSV-238235r853414_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

if [ -f /usr/bin/authselect ]; then
    if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
authselect enable-feature with-faillock

authselect apply-changes -b
else
    
conf_name=cac_faillock

if [ ! -f /usr/share/pam-configs/"$conf_name" ]; then
    cat << EOF > /usr/share/pam-configs/"$conf_name"
Name: Enable pam_faillock to deny access
Default: yes
Conflicts: faillock
Priority: 0
Auth-Type: Primary
Auth:
    [default=die]                   pam_faillock.so authfail
EOF
fi

if [ ! -f /usr/share/pam-configs/"$conf_name"_notify ]; then
    cat << EOF > /usr/share/pam-configs/"$conf_name"_notify
Name: Notify of failed login attempts and reset count upon success
Default: yes
Conflicts: faillock_notify
Priority: 1025
Auth-Type: Primary
Auth:
    requisite                       pam_faillock.so preauth
Account-Type: Primary
Account:
    required                        pam_faillock.so
EOF
fi

DEBIAN_FRONTEND=noninteractive pam-auth-update


fi



AUTH_FILES=("/etc/pam.d/common-auth")
SKIP_FAILLOCK_CHECK=true

FAILLOCK_CONF="/etc/security/faillock.conf"
if [ -f $FAILLOCK_CONF ] || [ "$SKIP_FAILLOCK_CHECK" = "true" ]; then
    regex="^\s*silent"
    line="silent"
    if ! grep -q $regex $FAILLOCK_CONF; then
        echo $line >> $FAILLOCK_CONF
    fi
    
else
    for pam_file in "${AUTH_FILES[@]}"
    do
        if ! grep -qE '^\s*auth.*pam_faillock\.so (preauth|authfail).*silent' "$pam_file"; then
            sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*preauth.*silent.*/ s/$/ silent/' "$pam_file"
        fi
    done
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010072
  - accounts_passwords_pam_faillock_silent
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Check
    if system relies on authselect tool
  ansible.builtin.stat:
    path: /usr/bin/authselect
  register: result_authselect_present
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010072
  - accounts_passwords_pam_faillock_silent
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Remediation
    where authselect tool is present
  block:

  - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Check
      integrity of authselect current profile
    ansible.builtin.command:
      cmd: authselect check
    register: result_authselect_check_cmd
    changed_when: false
    failed_when: false

  - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Informative
      message based on the authselect integrity check result
    ansible.builtin.assert:
      that:
      - result_authselect_check_cmd.rc == 0
      fail_msg:
      - authselect integrity check failed. Remediation aborted!
      - This remediation could not be applied because an authselect profile was not
        selected or the selected profile is not intact.
      - It is not recommended to manually edit the PAM files when authselect tool
        is available.
      - In cases where the default authselect profile does not cover a specific demand,
        a custom authselect profile is recommended.
      success_msg:
      - authselect integrity check passed

  - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Get
      authselect current features
    ansible.builtin.shell:
      cmd: authselect current | tail -n+3 | awk '{ print $2 }'
    register: result_authselect_features
    changed_when: false
    when:
    - result_authselect_check_cmd is success

  - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Ensure
      "with-faillock" feature is enabled using authselect tool
    ansible.builtin.command:
      cmd: authselect enable-feature with-faillock
    register: result_authselect_enable_feature_cmd
    when:
    - result_authselect_check_cmd is success
    - result_authselect_features.stdout is not search("with-faillock")

  - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Ensure
      authselect changes are applied
    ansible.builtin.command:
      cmd: authselect apply-changes -b
    when:
    - result_authselect_enable_feature_cmd is not skipped
    - result_authselect_enable_feature_cmd is success
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - result_authselect_present.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010072
  - accounts_passwords_pam_faillock_silent
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Remediation
    where authselect tool is not present
  block:

  - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Check
      if pam_faillock.so is already enabled
    ansible.builtin.lineinfile:
      path: /etc/pam.d/system-auth
      regexp: .*auth.*pam_faillock\.so (preauth|authfail)
      state: absent
    check_mode: true
    changed_when: false
    register: result_pam_faillock_is_enabled

  - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Enable
      pam_faillock.so preauth editing PAM files
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      line: auth        required      pam_faillock.so preauth
      insertbefore: ^auth.*sufficient.*pam_unix\.so.*
      state: present
    loop:
    - /etc/pam.d/system-auth
    - /etc/pam.d/password-auth
    when:
    - result_pam_faillock_is_enabled.found == 0

  - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Enable
      pam_faillock.so authfail editing PAM files
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      line: auth        required      pam_faillock.so authfail
      insertbefore: ^auth.*required.*pam_deny\.so.*
      state: present
    loop:
    - /etc/pam.d/system-auth
    - /etc/pam.d/password-auth
    when:
    - result_pam_faillock_is_enabled.found == 0

  - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Enable
      pam_faillock.so account section editing PAM files
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      line: account     required      pam_faillock.so
      insertbefore: ^account.*required.*pam_unix\.so.*
      state: present
    loop:
    - /etc/pam.d/system-auth
    - /etc/pam.d/password-auth
    when:
    - result_pam_faillock_is_enabled.found == 0
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - not result_authselect_present.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010072
  - accounts_passwords_pam_faillock_silent
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Check
    the presence of /etc/security/faillock.conf file
  ansible.builtin.stat:
    path: /etc/security/faillock.conf
  register: result_faillock_conf_check
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010072
  - accounts_passwords_pam_faillock_silent
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Ensure
    the pam_faillock.so silent parameter in /etc/security/faillock.conf
  ansible.builtin.lineinfile:
    path: /etc/security/faillock.conf
    regexp: ^\s*silent
    line: silent
    state: present
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - result_faillock_conf_check.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010072
  - accounts_passwords_pam_faillock_silent
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Ensure
    the pam_faillock.so silent parameter in PAM files
  block:

  - name: Do Not Show System Messages When Unsuccessful Logon Attempts Occur - Ensure
      the inclusion of pam_faillock.so preauth silent parameter in auth section
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      backrefs: true
      regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth(:?(?!silent).)*)
      line: \1required\3 silent
      state: present
    loop:
    - /etc/pam.d/system-auth
    - /etc/pam.d/password-auth
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - not result_faillock_conf_check.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010072
  - accounts_passwords_pam_faillock_silent
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

Rule   Set Lockout Time for Failed Password Attempts   [ref]

This rule configures the system to lock out accounts during a specified time period after a number of incorrect login attempts using pam_faillock.so. Ensure that the file /etc/security/faillock.conf contains the following entry: unlock_time=<interval-in-seconds> where interval-in-seconds is 0 or greater. pam_faillock.so module requires multiple entries in pam files. These entries must be carefully defined to work as expected. In order to avoid any errors when manually editing these files, it is recommended to use the appropriate tools, such as authselect or authconfig, depending on the OS version. If unlock_time is set to 0, manual intervention by an administrator is required to unlock a user. This should be done using the faillock tool.
Warning:  If the system supports the new /etc/security/faillock.conf file but the pam_faillock.so parameters are defined directly in /etc/pam.d/system-auth and /etc/pam.d/password-auth, the remediation will migrate the unlock_time parameter to /etc/security/faillock.conf to ensure compatibility with authselect tool. The parameters deny and fail_interval, if used, also have to be migrated by their respective remediation.
Warning:  If the system relies on authselect tool to manage PAM settings, the remediation will also use authselect tool. However, if any manual modification was made in PAM files, the authselect integrity check will fail and the remediation will be aborted in order to preserve intentional changes. In this case, an informative message will be shown in the remediation report. If the system supports the /etc/security/faillock.conf file, the pam_faillock parameters should be defined in faillock.conf file.
Rationale:
By limiting the number of failed logon attempts the risk of unauthorized system access via user password guessing, otherwise known as brute-forcing, is reduced. Limits are imposed by locking the account.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_passwords_pam_faillock_unlock_time
References:
cis-csc1, 12, 15, 16
cjis5.5.3
cobit5DSS05.04, DSS05.10, DSS06.10
cui3.1.8
disaCCI-000044, CCI-002238
isa-62443-20094.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9
ism0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561
iso27001-2013A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3
nistCM-6(a), AC-7(b)
nist-csfPR.AC-7
osppFIA_AFL.1
pcidssReq-8.1.7
os-srgSRG-OS-000329-GPOS-00128, SRG-OS-000021-GPOS-00005
stigidUBTU-20-010072
anssiR31
pcidss48.3.4, 8.3
stigrefSV-238235r853414_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_accounts_passwords_pam_faillock_unlock_time='0'


if [ -f /usr/bin/authselect ]; then
    if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
authselect enable-feature with-faillock

authselect apply-changes -b
else
    
conf_name=cac_faillock

if [ ! -f /usr/share/pam-configs/"$conf_name" ]; then
    cat << EOF > /usr/share/pam-configs/"$conf_name"
Name: Enable pam_faillock to deny access
Default: yes
Conflicts: faillock
Priority: 0
Auth-Type: Primary
Auth:
    [default=die]                   pam_faillock.so authfail
EOF
fi

if [ ! -f /usr/share/pam-configs/"$conf_name"_notify ]; then
    cat << EOF > /usr/share/pam-configs/"$conf_name"_notify
Name: Notify of failed login attempts and reset count upon success
Default: yes
Conflicts: faillock_notify
Priority: 1025
Auth-Type: Primary
Auth:
    requisite                       pam_faillock.so preauth
Account-Type: Primary
Account:
    required                        pam_faillock.so
EOF
fi

DEBIAN_FRONTEND=noninteractive pam-auth-update


fi

AUTH_FILES=("/etc/pam.d/common-auth")
SKIP_FAILLOCK_CHECK=true

FAILLOCK_CONF="/etc/security/faillock.conf"
if [ -f $FAILLOCK_CONF ] || [ "$SKIP_FAILLOCK_CHECK" = "true" ]; then
    regex="^\s*unlock_time\s*="
    line="unlock_time = $var_accounts_passwords_pam_faillock_unlock_time"
    if ! grep -q $regex $FAILLOCK_CONF; then
        echo $line >> $FAILLOCK_CONF
    else
        sed -i --follow-symlinks 's|^\s*\(unlock_time\s*=\s*\)\(\S\+\)|\1'"$var_accounts_passwords_pam_faillock_unlock_time"'|g' $FAILLOCK_CONF
    fi
    
else
    for pam_file in "${AUTH_FILES[@]}"
    do
        if ! grep -qE '^\s*auth.*pam_faillock\.so (preauth|authfail).*unlock_time' "$pam_file"; then
            sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*preauth.*silent.*/ s/$/ unlock_time='"$var_accounts_passwords_pam_faillock_unlock_time"'/' "$pam_file"
            sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*authfail.*/ s/$/ unlock_time='"$var_accounts_passwords_pam_faillock_unlock_time"'/' "$pam_file"
        else
            sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock\.so.*preauth.*silent.*\)\('"unlock_time"'=\)[0-9]\+\(.*\)/\1\2'"$var_accounts_passwords_pam_faillock_unlock_time"'\3/' "$pam_file"
            sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock\.so.*authfail.*\)\('"unlock_time"'=\)[0-9]\+\(.*\)/\1\2'"$var_accounts_passwords_pam_faillock_unlock_time"'\3/' "$pam_file"
        fi
    done
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
Group   Set Password Quality Requirements   Group contains 1 group and 9 rules
[ref]   The default pam_pwquality PAM module provides strength checking for passwords. It performs a number of checks, such as making sure passwords are not similar to dictionary words, are of at least a certain length, are not the previous password reversed, and are not simply a change of case from the previous password. It can also require passwords to be in certain character classes. The pam_pwquality module is the preferred way of configuring password requirements.

The man pages pam_pwquality(8) provide information on the capabilities and configuration of each.
Group   Set Password Quality Requirements with pam_pwquality   Group contains 9 rules
[ref]   The pam_pwquality PAM module can be configured to meet requirements for a variety of policies.

For example, to configure pam_pwquality to require at least one uppercase character, lowercase character, digit, and other (special) character, make sure that pam_pwquality exists in /etc/pam.d/system-auth:
password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
If no such line exists, add one as the first line of the password section in /etc/pam.d/system-auth. Next, modify the settings in /etc/security/pwquality.conf to match the following:
difok = 4
minlen = 14
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
maxrepeat = 3
The arguments can be modified to ensure compliance with your organization's security policy. Discussion of each parameter follows.

Rule   Ensure PAM Enforces Password Requirements - Minimum Digit Characters   [ref]

The pam_pwquality module's dcredit parameter controls requirements for usage of digits in a password. When set to a negative number, any password will be required to contain that many digits. When set to a positive number, pam_pwquality will grant +1 additional length credit for each digit. Modify the dcredit setting in /etc/security/pwquality.conf to require the use of a digit in passwords.
Rationale:
Use of a complex password helps to increase the time and resources required to compromise the password. Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks.

Password complexity is one factor of several that determines how long it takes to crack a password. The more complex the password, the greater the number of possible combinations that need to be tested before the password is compromised. Requiring digits makes password guessing attacks more difficult by ensuring a larger search space.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_password_pam_dcredit
References:
cis-csc1, 12, 15, 16, 5
cobit5DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
disaCCI-004066
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1
ism0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561
iso27001-2013A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
nistIA-5(c), IA-5(1)(a), CM-6(a), IA-5(4)
nist-csfPR.AC-1, PR.AC-6, PR.AC-7
osppFMT_SMF_EXT.1
pcidssReq-8.2.3
os-srgSRG-OS-000071-GPOS-00039
stigidUBTU-20-010052
cis5.3.1
anssiR31
pcidss48.3.6, 8.3
stigrefSV-238223r653844_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_password_pam_dcredit='-1'








# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^dcredit")

# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_dcredit"

# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^dcredit\\>" "/etc/security/pwquality.conf"; then
    escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
    LC_ALL=C sed -i --follow-symlinks "s/^dcredit\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
    if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
        LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
    fi
    printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010052
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.6
  - accounts_password_pam_dcredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: XCCDF Value var_password_pam_dcredit # promote to variable
  set_fact:
    var_password_pam_dcredit: !!str -1
  tags:
    - always

- name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Check
    if system relies on pam-auth-update tool
  ansible.builtin.stat:
    path: /usr/sbin/pam-auth-update
  register: result_pam_auth_update_present
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010052
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.6
  - accounts_password_pam_dcredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Remediation
    where pam-auth-update tool is present
  block:

  - name: Check if /usr/share/pam-configs/cac_pwquality exists
    stat:
      path: /usr/share/pam-configs/cac_pwquality
    register: pwquality_file_stat

  - name: Put the content into /usr/share/pam-configs/cac_pwquality if it does not
      exist
    copy:
      dest: /usr/share/pam-configs/cac_pwquality
      content: |
        Name: Pwquality password strength checking
        Default: yes
        Priority: 1024
        Conflicts: cracklib
        Password-Type: Primary
        Password:
          requisite           pam_pwquality.so retry=3
      force: true
    when: not pwquality_file_stat.stat.exists

  - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Ensure
      pam-auth-update profile changes are applied
    ansible.builtin.command:
      cmd: pam-auth-update --enable cac_pwquality
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - result_pam_auth_update_present.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010052
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.6
  - accounts_password_pam_dcredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Ensure
    PAM variable dcredit is set accordingly
  ansible.builtin.lineinfile:
    create: true
    dest: /etc/security/pwquality.conf
    regexp: ^#?\s*dcredit
    line: dcredit = {{ var_password_pam_dcredit }}
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010052
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.6
  - accounts_password_pam_dcredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

Rule   Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary Words   [ref]

The pam_pwquality module's dictcheck check if passwords contains dictionary words. When dictcheck is set to 1 passwords will be checked for dictionary words.
Rationale:
Use of a complex password helps to increase the time and resources required to compromise the password. Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks.

Password complexity is one factor of several that determines how long it takes to crack a password. The more complex the password, the greater the number of possible combinations that need to be tested before the password is compromised.

Passwords with dictionary words may be more vulnerable to password-guessing attacks.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_password_pam_dictcheck
References:
disaCCI-000366
nistIA-5(c), IA-5(1)(a), CM-6(a), IA-5(4)
os-srgSRG-OS-000480-GPOS-00225, SRG-OS-000072-GPOS-00040
stigidUBTU-20-010056
stigrefSV-238227r653856_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_password_pam_dictcheck='1'








# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^dictcheck")

# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_dictcheck"

# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^dictcheck\\>" "/etc/security/pwquality.conf"; then
    escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
    LC_ALL=C sed -i --follow-symlinks "s/^dictcheck\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
    if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
        LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
    fi
    printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010056
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - accounts_password_pam_dictcheck
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: XCCDF Value var_password_pam_dictcheck # promote to variable
  set_fact:
    var_password_pam_dictcheck: !!str 1
  tags:
    - always

- name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
    Words - Check if system relies on pam-auth-update tool
  ansible.builtin.stat:
    path: /usr/sbin/pam-auth-update
  register: result_pam_auth_update_present
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010056
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - accounts_password_pam_dictcheck
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
    Words - Remediation where pam-auth-update tool is present
  block:

  - name: Check if /usr/share/pam-configs/cac_pwquality exists
    stat:
      path: /usr/share/pam-configs/cac_pwquality
    register: pwquality_file_stat

  - name: Put the content into /usr/share/pam-configs/cac_pwquality if it does not
      exist
    copy:
      dest: /usr/share/pam-configs/cac_pwquality
      content: |
        Name: Pwquality password strength checking
        Default: yes
        Priority: 1024
        Conflicts: cracklib
        Password-Type: Primary
        Password:
          requisite           pam_pwquality.so retry=3
      force: true
    when: not pwquality_file_stat.stat.exists

  - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
      Words - Ensure pam-auth-update profile changes are applied
    ansible.builtin.command:
      cmd: pam-auth-update --enable cac_pwquality
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - result_pam_auth_update_present.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010056
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - accounts_password_pam_dictcheck
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
    Words - Ensure PAM variable dictcheck is set accordingly
  ansible.builtin.lineinfile:
    create: true
    dest: /etc/security/pwquality.conf
    regexp: ^#?\s*dictcheck
    line: dictcheck = {{ var_password_pam_dictcheck }}
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010056
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - accounts_password_pam_dictcheck
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

Rule   Ensure PAM Enforces Password Requirements - Minimum Different Characters   [ref]

The pam_pwquality module's difok parameter sets the number of characters in a password that must not be present in and old password during a password change.

Modify the difok setting in /etc/security/pwquality.conf to equal 8 to require differing characters when changing passwords.
Rationale:
Use of a complex password helps to increase the time and resources required to compromise the password. Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute–force attacks.

Password complexity is one factor of several that determines how long it takes to crack a password. The more complex the password, the greater the number of possible combinations that need to be tested before the password is compromised.

Requiring a minimum number of different characters during password changes ensures that newly changed passwords should not resemble previously compromised ones. Note that passwords which are changed on compromised systems will still be compromised, however.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_password_pam_difok
References:
cis-csc1, 12, 15, 16, 5
cjis5.6.2.1.1
cobit5DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
disaCCI-004066
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1
iso27001-2013A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
nistIA-5(c), IA-5(1)(b), CM-6(a), IA-5(4)
nist-csfPR.AC-1, PR.AC-6, PR.AC-7
os-srgSRG-OS-000072-GPOS-00040
stigidUBTU-20-010053
stigrefSV-238224r653847_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_password_pam_difok='8'








# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^difok")

# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_difok"

# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^difok\\>" "/etc/security/pwquality.conf"; then
    escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
    LC_ALL=C sed -i --follow-symlinks "s/^difok\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
    if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
        LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
    fi
    printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.6.2.1.1
  - DISA-STIG-UBTU-20-010053
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(b)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - accounts_password_pam_difok
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: XCCDF Value var_password_pam_difok # promote to variable
  set_fact:
    var_password_pam_difok: !!str 8
  tags:
    - always

- name: Ensure PAM Enforces Password Requirements - Minimum Different Characters -
    Check if system relies on pam-auth-update tool
  ansible.builtin.stat:
    path: /usr/sbin/pam-auth-update
  register: result_pam_auth_update_present
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - CJIS-5.6.2.1.1
  - DISA-STIG-UBTU-20-010053
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(b)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - accounts_password_pam_difok
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Minimum Different Characters -
    Remediation where pam-auth-update tool is present
  block:

  - name: Check if /usr/share/pam-configs/cac_pwquality exists
    stat:
      path: /usr/share/pam-configs/cac_pwquality
    register: pwquality_file_stat

  - name: Put the content into /usr/share/pam-configs/cac_pwquality if it does not
      exist
    copy:
      dest: /usr/share/pam-configs/cac_pwquality
      content: |
        Name: Pwquality password strength checking
        Default: yes
        Priority: 1024
        Conflicts: cracklib
        Password-Type: Primary
        Password:
          requisite           pam_pwquality.so retry=3
      force: true
    when: not pwquality_file_stat.stat.exists

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
      - Ensure pam-auth-update profile changes are applied
    ansible.builtin.command:
      cmd: pam-auth-update --enable cac_pwquality
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - result_pam_auth_update_present.stat.exists
  tags:
  - CJIS-5.6.2.1.1
  - DISA-STIG-UBTU-20-010053
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(b)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - accounts_password_pam_difok
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Minimum Different Characters -
    Ensure PAM variable difok is set accordingly
  ansible.builtin.lineinfile:
    create: true
    dest: /etc/security/pwquality.conf
    regexp: ^#?\s*difok
    line: difok = {{ var_password_pam_difok }}
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - CJIS-5.6.2.1.1
  - DISA-STIG-UBTU-20-010053
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(b)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - accounts_password_pam_difok
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

Rule   Ensure PAM Enforces Password Requirements - Enforcing   [ref]

Verify that the operating system uses "pwquality" to enforce the password complexity rules. Verify the pwquality module is being enforced by operating system by running the following command:
$ grep -i enforcing /etc/security/pwquality.conf
enforcing = 1
If the value of "enforcing" is not "1" or the line is commented out, this is a finding.
Rationale:
Use of a complex password helps to increase the time and resources required to compromise the password. Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks. Using enforcing=1 ensures "pwquality" enforces complex password construction configuration and has the ability to limit brute-force attacks on the system.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_password_pam_enforcing
References:
disaCCI-000366
os-srgSRG-OS-000480-GPOS-00225
stigidUBTU-20-010057
stigrefSV-238228r653859_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

if [ -e "/etc/security/pwquality.conf" ] ; then
    
    LC_ALL=C sed -i "/^\s*enforcing = 1/Id" "/etc/security/pwquality.conf"
else
    touch "/etc/security/pwquality.conf"
fi
# make sure file has newline at the end
sed -i -e '$a\' "/etc/security/pwquality.conf"

cp "/etc/security/pwquality.conf" "/etc/security/pwquality.conf.bak"
# Insert at the end of the file
printf '%s\n' "enforcing = 1" >> "/etc/security/pwquality.conf"
# Clean up after ourselves.
rm "/etc/security/pwquality.conf.bak"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010057
  - accounts_password_pam_enforcing
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Enforcing
  lineinfile:
    path: /etc/security/pwquality.conf
    create: true
    regexp: ''
    line: enforcing = 1
    state: present
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010057
  - accounts_password_pam_enforcing
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

Rule   Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters   [ref]

The pam_pwquality module's lcredit parameter controls requirements for usage of lowercase letters in a password. When set to a negative number, any password will be required to contain that many lowercase characters. When set to a positive number, pam_pwquality will grant +1 additional length credit for each lowercase character. Modify the lcredit setting in /etc/security/pwquality.conf to require the use of a lowercase character in passwords.
Rationale:
Use of a complex password helps to increase the time and resources required to compromise the password. Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks.
Password complexity is one factor of several that determines how long it takes to crack a password. The more complex the password, the greater the number of possble combinations that need to be tested before the password is compromised. Requiring a minimum number of lowercase characters makes password guessing attacks more difficult by ensuring a larger search space.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_password_pam_lcredit
References:
cis-csc1, 12, 15, 16, 5
cobit5DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
disaCCI-004066
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1
ism0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561
iso27001-2013A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
nistIA-5(c), IA-5(1)(a), CM-6(a), IA-5(4)
nist-csfPR.AC-1, PR.AC-6, PR.AC-7
osppFMT_SMF_EXT.1
pcidssReq-8.2.3
os-srgSRG-OS-000070-GPOS-00038
stigidUBTU-20-010051
cis5.3.1
anssiR31
pcidss48.3.6, 8.3
stigrefSV-238222r653841_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_password_pam_lcredit='-1'








# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^lcredit")

# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_lcredit"

# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^lcredit\\>" "/etc/security/pwquality.conf"; then
    escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
    LC_ALL=C sed -i --follow-symlinks "s/^lcredit\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
    if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
        LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
    fi
    printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010051
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.6
  - accounts_password_pam_lcredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: XCCDF Value var_password_pam_lcredit # promote to variable
  set_fact:
    var_password_pam_lcredit: !!str -1
  tags:
    - always

- name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters -
    Check if system relies on pam-auth-update tool
  ansible.builtin.stat:
    path: /usr/sbin/pam-auth-update
  register: result_pam_auth_update_present
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010051
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.6
  - accounts_password_pam_lcredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters -
    Remediation where pam-auth-update tool is present
  block:

  - name: Check if /usr/share/pam-configs/cac_pwquality exists
    stat:
      path: /usr/share/pam-configs/cac_pwquality
    register: pwquality_file_stat

  - name: Put the content into /usr/share/pam-configs/cac_pwquality if it does not
      exist
    copy:
      dest: /usr/share/pam-configs/cac_pwquality
      content: |
        Name: Pwquality password strength checking
        Default: yes
        Priority: 1024
        Conflicts: cracklib
        Password-Type: Primary
        Password:
          requisite           pam_pwquality.so retry=3
      force: true
    when: not pwquality_file_stat.stat.exists

  - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
      - Ensure pam-auth-update profile changes are applied
    ansible.builtin.command:
      cmd: pam-auth-update --enable cac_pwquality
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - result_pam_auth_update_present.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010051
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.6
  - accounts_password_pam_lcredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters -
    Ensure PAM variable lcredit is set accordingly
  ansible.builtin.lineinfile:
    create: true
    dest: /etc/security/pwquality.conf
    regexp: ^#?\s*lcredit
    line: lcredit = {{ var_password_pam_lcredit }}
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010051
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.6
  - accounts_password_pam_lcredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

Rule   Ensure PAM Enforces Password Requirements - Minimum Length   [ref]

The pam_pwquality module's minlen parameter controls requirements for minimum characters required in a password. Add minlen=15 after pam_pwquality to set minimum password length requirements.
Rationale:
The shorter the password, the lower the number of possible combinations that need to be tested before the password is compromised.
Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks. Password length is one factor of several that helps to determine strength and how long it takes to crack a password. Use of more characters in a password helps to exponentially increase the time and/or resources required to compromise the password.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_password_pam_minlen
References:
cis-csc1, 12, 15, 16, 5
cjis5.6.2.1.1
cobit5DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
disaCCI-004066
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1
ism0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561
iso27001-2013A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
nistIA-5(c), IA-5(1)(a), CM-6(a), IA-5(4)
nist-csfPR.AC-1, PR.AC-6, PR.AC-7
osppFMT_SMF_EXT.1
pcidssReq-8.2.3
os-srgSRG-OS-000078-GPOS-00046
stigidUBTU-20-010054
cis5.3.1
anssiR31, R68
pcidss48.3.6, 8.3
stigrefSV-238225r832942_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_password_pam_minlen='15'








# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^minlen")

# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_minlen"

# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^minlen\\>" "/etc/security/pwquality.conf"; then
    escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
    LC_ALL=C sed -i --follow-symlinks "s/^minlen\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
    if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
        LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
    fi
    printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.6.2.1.1
  - DISA-STIG-UBTU-20-010054
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.6
  - accounts_password_pam_minlen
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: XCCDF Value var_password_pam_minlen # promote to variable
  set_fact:
    var_password_pam_minlen: !!str 15
  tags:
    - always

- name: Ensure PAM Enforces Password Requirements - Minimum Length - Check if system
    relies on pam-auth-update tool
  ansible.builtin.stat:
    path: /usr/sbin/pam-auth-update
  register: result_pam_auth_update_present
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - CJIS-5.6.2.1.1
  - DISA-STIG-UBTU-20-010054
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.6
  - accounts_password_pam_minlen
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Minimum Length - Remediation where
    pam-auth-update tool is present
  block:

  - name: Check if /usr/share/pam-configs/cac_pwquality exists
    stat:
      path: /usr/share/pam-configs/cac_pwquality
    register: pwquality_file_stat

  - name: Put the content into /usr/share/pam-configs/cac_pwquality if it does not
      exist
    copy:
      dest: /usr/share/pam-configs/cac_pwquality
      content: |
        Name: Pwquality password strength checking
        Default: yes
        Priority: 1024
        Conflicts: cracklib
        Password-Type: Primary
        Password:
          requisite           pam_pwquality.so retry=3
      force: true
    when: not pwquality_file_stat.stat.exists

  - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure pam-auth-update
      profile changes are applied
    ansible.builtin.command:
      cmd: pam-auth-update --enable cac_pwquality
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - result_pam_auth_update_present.stat.exists
  tags:
  - CJIS-5.6.2.1.1
  - DISA-STIG-UBTU-20-010054
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.6
  - accounts_password_pam_minlen
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure PAM variable
    minlen is set accordingly
  ansible.builtin.lineinfile:
    create: true
    dest: /etc/security/pwquality.conf
    regexp: ^#?\s*minlen
    line: minlen = {{ var_password_pam_minlen }}
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - CJIS-5.6.2.1.1
  - DISA-STIG-UBTU-20-010054
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.6
  - accounts_password_pam_minlen
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

Rule   Ensure PAM Enforces Password Requirements - Minimum Special Characters   [ref]

The pam_pwquality module's ocredit= parameter controls requirements for usage of special (or "other") characters in a password. When set to a negative number, any password will be required to contain that many special characters. When set to a positive number, pam_pwquality will grant +1 additional length credit for each special character. Modify the ocredit setting in /etc/security/pwquality.conf to equal -1 to require use of a special character in passwords.
Rationale:
Use of a complex password helps to increase the time and resources required to compromise the password. Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks.

Password complexity is one factor of several that determines how long it takes to crack a password. The more complex the password, the greater the number of possible combinations that need to be tested before the password is compromised. Requiring a minimum number of special characters makes password guessing attacks more difficult by ensuring a larger search space.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_password_pam_ocredit
References:
cis-csc1, 12, 15, 16, 5
cobit5DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
disaCCI-004066
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1
ism0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561
iso27001-2013A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
nistIA-5(c), IA-5(1)(a), CM-6(a), IA-5(4)
nist-csfPR.AC-1, PR.AC-6, PR.AC-7
osppFMT_SMF_EXT.1
os-srgSRG-OS-000266-GPOS-00101
stigidUBTU-20-010055
cis5.3.1
anssiR31
stigrefSV-238226r653853_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_password_pam_ocredit='-1'








# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^ocredit")

# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_ocredit"

# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^ocredit\\>" "/etc/security/pwquality.conf"; then
    escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
    LC_ALL=C sed -i --follow-symlinks "s/^ocredit\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
    if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
        LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
    fi
    printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010055
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - accounts_password_pam_ocredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: XCCDF Value var_password_pam_ocredit # promote to variable
  set_fact:
    var_password_pam_ocredit: !!str -1
  tags:
    - always

- name: Ensure PAM Enforces Password Requirements - Minimum Special Characters - Check
    if system relies on pam-auth-update tool
  ansible.builtin.stat:
    path: /usr/sbin/pam-auth-update
  register: result_pam_auth_update_present
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010055
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - accounts_password_pam_ocredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Minimum Special Characters - Remediation
    where pam-auth-update tool is present
  block:

  - name: Check if /usr/share/pam-configs/cac_pwquality exists
    stat:
      path: /usr/share/pam-configs/cac_pwquality
    register: pwquality_file_stat

  - name: Put the content into /usr/share/pam-configs/cac_pwquality if it does not
      exist
    copy:
      dest: /usr/share/pam-configs/cac_pwquality
      content: |
        Name: Pwquality password strength checking
        Default: yes
        Priority: 1024
        Conflicts: cracklib
        Password-Type: Primary
        Password:
          requisite           pam_pwquality.so retry=3
      force: true
    when: not pwquality_file_stat.stat.exists

  - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters -
      Ensure pam-auth-update profile changes are applied
    ansible.builtin.command:
      cmd: pam-auth-update --enable cac_pwquality
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - result_pam_auth_update_present.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010055
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - accounts_password_pam_ocredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Minimum Special Characters - Ensure
    PAM variable ocredit is set accordingly
  ansible.builtin.lineinfile:
    create: true
    dest: /etc/security/pwquality.conf
    regexp: ^#?\s*ocredit
    line: ocredit = {{ var_password_pam_ocredit }}
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010055
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - accounts_password_pam_ocredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

Rule   Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session   [ref]

To configure the number of retry prompts that are permitted per-session: Edit the pam_pwquality.so statement in /etc/pam.d/common-password to show retry=3 , or a lower value if site policy is more restrictive. The DoD requirement is a maximum of 3 prompts per session.
Rationale:
Setting the password retry prompts that are permitted on a per-session basis to a low value requires some software, such as SSH, to re-connect. This can slow down and draw additional attention to some types of password-guessing attacks. Note that this is different from account lockout, which is provided by the pam_faillock module.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_password_pam_retry
References:
cis-csc1, 11, 12, 15, 16, 3, 5, 9
cjis5.5.3
cobit5BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
disaCCI-004066
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 7.6
iso27001-2013A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
nistCM-6(a), AC-7(a), IA-5(4)
nist-csfPR.AC-1, PR.AC-6, PR.AC-7, PR.IP-1
os-srgSRG-OS-000069-GPOS-00037, SRG-OS-000480-GPOS-00227
stigidUBTU-20-010057
cis5.3.1
anssiR68
stigrefSV-238228r653859_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_password_pam_retry='3'


conf_name=cac_pwquality
if [ ! -f /usr/share/pam-configs/"$conf_name" ]; then
    cat << EOF > /usr/share/pam-configs/"$conf_name"
Name: Pwquality password strength checking
Default: yes
Priority: 1025
Conflicts: cracklib, pwquality
Password-Type: Primary
Password:
    requisite                   pam_pwquality.so
EOF
fi

DEBIAN_FRONTEND=noninteractive pam-auth-update
PWQUALITY_CONF="/etc/security/pwquality.conf"
    regex="^\s*retry\s*="
    line="retry = $var_password_pam_retry"
    if ! grep -q $regex $PWQUALITY_CONF; then
        echo $line >> $PWQUALITY_CONF
    else
        sed -i --follow-symlinks 's|^\s*\(retry\s*=\s*\)\(\S\+\)|\1'"$var_password_pam_retry"'|g' $PWQUALITY_CONF
    fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Rule   Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters   [ref]

The pam_pwquality module's ucredit= parameter controls requirements for usage of uppercase letters in a password. When set to a negative number, any password will be required to contain that many uppercase characters. When set to a positive number, pam_pwquality will grant +1 additional length credit for each uppercase character. Modify the ucredit setting in /etc/security/pwquality.conf to require the use of an uppercase character in passwords.
Rationale:
Use of a complex password helps to increase the time and resources required to compromise the password. Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks.

Password complexity is one factor of several that determines how long it takes to crack a password. The more complex the password, the greater the number of possible combinations that need to be tested before the password is compromised.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_password_pam_ucredit
References:
cis-csc1, 12, 15, 16, 5
cobit5DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
disaCCI-004066
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1
ism0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561
iso27001-2013A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
nistIA-5(c), IA-5(1)(a), CM-6(a), IA-5(4)
nist-csfPR.AC-1, PR.AC-6, PR.AC-7
osppFMT_SMF_EXT.1
pcidssReq-8.2.3
os-srgSRG-OS-000069-GPOS-00037, SRG-OS-000070-GPOS-00038
stigidUBTU-20-010050
cis5.3.1
anssiR31
stigrefSV-238221r653838_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

var_password_pam_ucredit='-1'








# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^ucredit")

# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_ucredit"

# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^ucredit\\>" "/etc/security/pwquality.conf"; then
    escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
    LC_ALL=C sed -i --follow-symlinks "s/^ucredit\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
    if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
        LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
    fi
    printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010050
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - accounts_password_pam_ucredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: XCCDF Value var_password_pam_ucredit # promote to variable
  set_fact:
    var_password_pam_ucredit: !!str -1
  tags:
    - always

- name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters -
    Check if system relies on pam-auth-update tool
  ansible.builtin.stat:
    path: /usr/sbin/pam-auth-update
  register: result_pam_auth_update_present
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010050
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - accounts_password_pam_ucredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters -
    Remediation where pam-auth-update tool is present
  block:

  - name: Check if /usr/share/pam-configs/cac_pwquality exists
    stat:
      path: /usr/share/pam-configs/cac_pwquality
    register: pwquality_file_stat

  - name: Put the content into /usr/share/pam-configs/cac_pwquality if it does not
      exist
    copy:
      dest: /usr/share/pam-configs/cac_pwquality
      content: |
        Name: Pwquality password strength checking
        Default: yes
        Priority: 1024
        Conflicts: cracklib
        Password-Type: Primary
        Password:
          requisite           pam_pwquality.so retry=3
      force: true
    when: not pwquality_file_stat.stat.exists

  - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
      - Ensure pam-auth-update profile changes are applied
    ansible.builtin.command:
      cmd: pam-auth-update --enable cac_pwquality
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - result_pam_auth_update_present.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010050
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - accounts_password_pam_ucredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters -
    Ensure PAM variable ucredit is set accordingly
  ansible.builtin.lineinfile:
    create: true
    dest: /etc/security/pwquality.conf
    regexp: ^#?\s*ucredit
    line: ucredit = {{ var_password_pam_ucredit }}
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010050
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(4)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - accounts_password_pam_ucredit
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
Group   Set Password Hashing Algorithm   Group contains 1 rule
[ref]   The system's default algorithm for storing password hashes in /etc/shadow is SHA-512. This can be configured in several locations.

Rule   Set Password Hashing Algorithm in /etc/login.defs   [ref]

In /etc/login.defs, add or update the following line to ensure the system will use SHA512 as the hashing algorithm:
ENCRYPT_METHOD SHA512
         
Rationale:
Passwords need to be protected at all times, and encryption is the standard method for protecting passwords. If passwords are not encrypted, they can be plainly read (i.e., clear text) and easily compromised. Passwords that are encrypted with a weak algorithm are no more protected than if they are kept in plain text.

Using a stronger hashing algorithm makes password cracking attacks more difficult.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_logindefs
References:
cis-csc1, 12, 15, 16, 5
cjis5.6.2.2
cobit5DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
cui3.13.11
disaCCI-004062
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1
ism0418, 1055, 1402
iso27001-2013A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
nistIA-5(c), IA-5(1)(c), CM-6(a)
nist-csfPR.AC-1, PR.AC-6, PR.AC-7
pcidssReq-8.2.1
os-srgSRG-OS-000073-GPOS-00041
stigidUBTU-20-010404
pcidss48.3.2, 8.3
stigrefSV-238325r654150_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'login' 2>/dev/null | grep -q installed; then

var_password_hashing_algorithm='SHA512'


# Allow multiple algorithms, but choose the first one for remediation
#
var_password_hashing_algorithm="$(echo $var_password_hashing_algorithm | cut -d \| -f 1)"

# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^ENCRYPT_METHOD")

# shellcheck disable=SC2059
printf -v formatted_output "%s %s" "$stripped_key" "$var_password_hashing_algorithm"

# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^ENCRYPT_METHOD\\>" "/etc/login.defs"; then
    escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
    LC_ALL=C sed -i --follow-symlinks "s/^ENCRYPT_METHOD\\>.*/$escaped_formatted_output/gi" "/etc/login.defs"
else
    if [[ -s "/etc/login.defs" ]] && [[ -n "$(tail -c 1 -- "/etc/login.defs" || true)" ]]; then
        LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/login.defs"
    fi
    printf '%s\n' "$formatted_output" >> "/etc/login.defs"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Rule   Install pam_pwquality Package   [ref]

The libpam-pwquality package can be installed with the following command:
$ apt-get install libpam-pwquality
Rationale:
Use of a complex password helps to increase the time and resources required to compromise the password. Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks. "pwquality" enforces complex password construction configuration and has the ability to limit brute-force attacks on the system.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_package_pam_pwquality_installed
References:
disaCCI-000366
os-srgSRG-OS-000480-GPOS-00225
stigidUBTU-20-010057
cis5.3.1
stigrefSV-238228r653859_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

DEBIAN_FRONTEND=noninteractive apt-get install -y "libpam-pwquality"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


[[packages]]
name = "libpam-pwquality"
version = "*"

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010057
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - package_pam_pwquality_installed

- name: Ensure libpam-pwquality is installed
  package:
    name: libpam-pwquality
    state: present
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010057
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - package_pam_pwquality_installed

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
include install_libpam-pwquality

class install_libpam-pwquality {
  package { 'libpam-pwquality':
    ensure => 'installed',
  }
}
Group   Protect Physical Console Access   Group contains 3 groups and 9 rules
[ref]   It is impossible to fully protect a system from an attacker with physical access, so securing the space in which the system is located should be considered a necessary step. However, there are some steps which, if taken, make it more difficult for an attacker to quickly or undetectably modify a system from its console.
Group   Configure Screen Locking   Group contains 2 groups and 8 rules
[ref]   When a user must temporarily leave an account logged-in, screen locking should be employed to prevent passersby from abusing the account. User education and training is particularly important for screen locking to be effective, and policies can be implemented to reinforce this.

Automatic screen locking is only meant as a safeguard for those cases where a user forgot to lock the screen.
Group   Configure Console Screen Locking   Group contains 1 rule
[ref]   A console screen locking mechanism is a temporary action taken when a user stops work and moves away from the immediate physical vicinity of the information system but does not logout because of the temporary nature of the absence. Rather than relying on the user to manually lock their operation system session prior to vacating the vicinity, operating systems need to be able to identify when a user's session has idled and take action to initiate the session lock.

Rule   Check that vlock is installed to allow session locking   [ref]

The Ubuntu 20.04 operating system must have vlock installed to allow for session locking. The vlock package can be installed with the following command:
$ apt-get install vlock
Rationale:
A session lock is a temporary action taken when a user stops work and moves away from the immediate physical vicinity of the information system but does not want to log out because of the temporary nature of the absence. The session lock is implemented at the point where session activity can be determined. Regardless of where the session lock is determined and implemented, once invoked, the session lock must remain in place until the user reauthenticates. No other activity aside from reauthentication must unlock the system.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_vlock_installed
References:
disaCCI-000056, CCI-000057, CCI-000058, CCI-000060
os-srgSRG-OS-000028-GPOS-00009, SRG-OS-000030-GPOS-00011
stigidUBTU-20-010005
stigrefSV-238200r653775_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

DEBIAN_FRONTEND=noninteractive apt-get install -y "vlock"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


[[packages]]
name = "vlock"
version = "*"

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010005
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - vlock_installed

- name: Ensure vlock is installed
  package:
    name: vlock
    state: present
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010005
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - vlock_installed

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
include install_vlock

class install_vlock {
  package { 'vlock':
    ensure => 'installed',
  }
}
Group   Hardware Tokens for Authentication   Group contains 7 rules

Rule   Install the opensc Package For Multifactor Authentication   [ref]

The opensc-pkcs11 package can be installed with the following command:
$ apt-get install opensc-pkcs11
Rationale:
Using an authentication device, such as a CAC or token that is separate from the information system, ensures that even if the information system is compromised, that compromise will not affect credentials stored on the authentication device.

Multifactor solutions that require devices separate from information systems gaining access include, for example, hardware tokens providing time-based or challenge-response authenticators and smart cards such as the U.S. Government Personal Identity Verification card and the DoD Common Access Card.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_package_opensc_installed
References:
disaCCI-001953, CCI-004046
ism1382, 1384, 1386
nistCM-6(a)
os-srgSRG-OS-000375-GPOS-00160, SRG-OS-000376-GPOS-00161
stigidUBTU-20-010064
stigrefSV-238231r853411_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

DEBIAN_FRONTEND=noninteractive apt-get install -y "opensc-pkcs11"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


[[packages]]
name = "opensc-pkcs11"
version = "*"

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010064
  - NIST-800-53-CM-6(a)
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - package_opensc_installed

- name: Ensure opensc-pkcs11 is installed
  package:
    name: opensc-pkcs11
    state: present
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010064
  - NIST-800-53-CM-6(a)
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - package_opensc_installed

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
include install_opensc-pkcs11

class install_opensc-pkcs11 {
  package { 'opensc-pkcs11':
    ensure => 'installed',
  }
}

Rule   Install Smart Card Packages For Multifactor Authentication   [ref]

Configure the operating system to implement multifactor authentication by installing the required package with the following command: The libpam-pkcs11 package can be installed with the following command:
$ apt-get install libpam-pkcs11
Rationale:
Using an authentication device, such as a CAC or token that is separate from the information system, ensures that even if the information system is compromised, that compromise will not affect credentials stored on the authentication device.

Multifactor solutions that require devices separate from information systems gaining access include, for example, hardware tokens providing time-based or challenge-response authenticators and smart cards such as the U.S. Government Personal Identity Verification card and the DoD Common Access Card.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_install_smartcard_packages
References:
disaCCI-000765, CCI-001953, CCI-001954, CCI-004046
nistCM-6(a)
pcidssReq-8.3
os-srgSRG-OS-000105-GPOS-00052, SRG-OS-000375-GPOS-00160, SRG-OS-000375-GPOS-00161, SRG-OS-000377-GPOS-00162
stigidUBTU-20-010063
stigrefSV-238230r853410_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed && { ! grep -q s390x /proc/sys/kernel/{osrelease,arch}; }; then

DEBIAN_FRONTEND=noninteractive apt-get install -y "libpam-pkcs11"

if [ ! -f /etc/pam_pkcs11/pam_pkcs11.conf ]; then
    cp /usr/share/doc/libpam-pkcs11/examples/pam_pkcs11.conf.example /etc/pam_pkcs11/pam_pkcs11.conf
fi

sed -i -e 's/debug = true/debug = false/g' -e 's|module = /usr/lib/opensc-pkcs11|module = /usr/lib/x86_64-linux-gnu/pkcs11/opensc-pkcs11|' /etc/pam_pkcs11/pam_pkcs11.conf

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


[[packages]]
name = "libpam-pkcs11"
version = "*"

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010063
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-8.3
  - enable_strategy
  - install_smartcard_packages
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure libpam-pkcs11 is installed
  package:
    name: libpam-pkcs11
    state: present
  when:
  - '"linux-base" in ansible_facts.packages'
  - ansible_architecture != "s390x"
  tags:
  - DISA-STIG-UBTU-20-010063
  - NIST-800-53-CM-6(a)
  - PCI-DSS-Req-8.3
  - enable_strategy
  - install_smartcard_packages
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
include install_libpam-pkcs11

class install_libpam-pkcs11 {
  package { 'libpam-pkcs11':
    ensure => 'installed',
  }
}

Rule   Configure Smart Card Certificate Authority Validation   [ref]

Configure the operating system to do certificate status checking for PKI authentication. Modify all of the cert_policy lines in /etc/pam_pkcs11/pam_pkcs11.conf to include ca like so:
cert_policy = ca, ocsp_on, signature;
Rationale:
Using an authentication device, such as a CAC or token that is separate from the information system, ensures that even if the information system is compromised, that compromise will not affect credentials stored on the authentication device.

Multifactor solutions that require devices separate from information systems gaining access include, for example, hardware tokens providing time-based or challenge-response authenticators and smart cards such as the U.S. Government Personal Identity Verification card and the DoD Common Access Card.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_smartcard_configure_ca
References:
disaCCI-000185, CCI-004068
os-srgSRG-OS-000066-GPOS-00034, SRG-OS-000384-GPOS-00167
stigidUBTU-20-010060
stigrefSV-238229r653862_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

if [ ! -f /etc/pam_pkcs11/pam_pkcs11.conf ]; then
    cp /usr/share/doc/libpam-pkcs11/examples/pam_pkcs11.conf.example /etc/pam_pkcs11/pam_pkcs11.conf
fi

if grep -v "^\s*\#+cert_policy" /etc/pam_pkcs11/pam_pkcs11.conf | grep -qv "ca"; then
    sed -i "s/\(^[[:blank:]]*\)\(\(\#*[[:blank:]]*cert_policy[[:blank:]]*=[[:blank:]]*.*;\)[^ $]*\)/\1cert_policy = ca,signature,ocsp_on;/" /etc/pam_pkcs11/pam_pkcs11.conf
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Rule   Configure Smart Card Certificate Status Checking   [ref]

Configure the operating system to do certificate status checking for PKI authentication. Modify all of the cert_policy lines in /etc/pam_pkcs11/pam_pkcs11.conf to include ocsp_on like so:
cert_policy = ca, ocsp_on, signature;
Rationale:
Using an authentication device, such as a CAC or token that is separate from the information system, ensures that even if the information system is compromised, that compromise will not affect credentials stored on the authentication device.

Multifactor solutions that require devices separate from information systems gaining access include, for example, hardware tokens providing time-based or challenge-response authenticators and smart cards such as the U.S. Government Personal Identity Verification card and the DoD Common Access Card.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_smartcard_configure_cert_checking
References:
disaCCI-004046, CCI-001953, CCI-001954
os-srgSRG-OS-000375-GPOS-00160, SRG-OS-000376-GPOS-00161, SRG-OS-000377-GPOS-00162, SRG-OS-000384-GPOS-00167
stigidUBTU-20-010065
stigrefSV-238232r853412_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed && { ! grep -q s390x /proc/sys/kernel/{osrelease,arch}; }; then

if [ ! -f /etc/pam_pkcs11/pam_pkcs11.conf ]; then
    cp /usr/share/doc/libpam-pkcs11/examples/pam_pkcs11.conf.example /etc/pam_pkcs11/pam_pkcs11.conf
fi

if grep -v "^\s*\#+cert_policy" /etc/pam_pkcs11/pam_pkcs11.conf | grep -qv "oscp_on"; then
    sed -i "s/\(^[[:blank:]]*\)\(\(\#*[[:blank:]]*cert_policy[[:blank:]]*=[[:blank:]]*.*;\)[^ $]*\)/\1cert_policy = ca,signature,ocsp_on;/" /etc/pam_pkcs11/pam_pkcs11.conf
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Rule   Configure Smart Card Local Cache of Revocation Data   [ref]

Configure the operating system for PKI-based authentication to use local revocation data when unable to access the network to obtain it remotely. Modify all of the cert_policy lines in /etc/pam_pkcs11/pam_pkcs11.conf to include crl_auto or crl_offline like so:
cert_policy = ca,signature,ocsp_on,crl_auto;
Rationale:
Without configuring a local cache of revocation data, there is the potential to allow access to users who are no longer authorized (users with revoked certificates).
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_smartcard_configure_crl
References:
disaCCI-004068, CCI-004068
os-srgSRG-OS-000384-GPOS-00167
stigidUBTU-20-010066
stigrefSV-238233r880870_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

if [ ! -f /etc/pam_pkcs11/pam_pkcs11.conf ]; then
    cp /usr/share/doc/libpam-pkcs11/examples/pam_pkcs11.conf.example /etc/pam_pkcs11/pam_pkcs11.conf
fi

if grep -v "^\s*\#+cert_policy" /etc/pam_pkcs11/pam_pkcs11.conf | grep -Eqv 'crl_auto|crl_offline'; then
    sed -i "s/\(^[[:blank:]]*\)\(\(\#*[[:blank:]]*cert_policy[[:blank:]]*=[[:blank:]]*.*;\)[^ $]*\)/\1cert_policy = ca,signature,ocsp_on,crl_auto;/" /etc/pam_pkcs11/pam_pkcs11.conf
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Rule   Enable Smart Card Logins in PAM   [ref]

This requirement only applies to components where this is specific to the function of the device or has the concept of an organizational user (e.g., VPN, proxy capability). This does not apply to authentication for the purpose of configuring the device itself (management). Add or update the following line in /etc/pam.d/common-auth, placing it above any lines containing pam_unix.so:
auth    [success=2 default=ignore] pam_pkcs11.so 
For general information about enabling smart card authentication, consult the documentation at:
Rationale:
Smart card login provides two-factor authentication stronger than that provided by a username and password combination. Smart cards leverage PKI (public key infrastructure) in order to provide and verify credentials. Using an authentication device, such as a CAC or token that is separate from the information system, ensures that even if the information system is compromised, that compromise will not affect credentials stored on the authentication device. Multifactor solutions that require devices separate from information systems gaining access include, for example, hardware tokens providing time-based or challenge-response authenticators and smart cards such as the U.S. Government Personal Identity Verification card and the DoD Common Access Card.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_smartcard_pam_enabled
References:
disaCCI-000765, CCI-000766, CCI-000767, CCI-000768, CCI-000187, CCI-004046, CCI-001953, CCI-001954, CCI-004047
os-srgSRG-OS-000068-GPOS-00036, SRG-OS-000105-GPOS-00052, SRG-OS-000106-GPOS-00053, SRG-OS-000107-GPOS-00054, SRG-OS-000108-GPOS-00055, SRG-OS-000375-GPOS-00160, SRG-OS-000375-GPOS-00161, SRG-OS-000375-GPOS-00162
stigidUBTU-20-010033
stigrefSV-238210r951462_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

if ! grep -qP "^\s*auth\s+\[success=2 default=ignore\]\s+pam_pkcs11.so\s*.*" "/etc/pam.d/common-auth"; then
    # Line matching group + control + module was not found. Check group + module.
    if [ "$(grep -cP '^\s*auth\s+.*\s+pam_pkcs11.so\s*' "/etc/pam.d/common-auth")" -eq 1 ]; then
        # The control is updated only if one single line matches.
        sed -i -E --follow-symlinks "s/^(\s*auth\s+).*(\bpam_pkcs11.so.*)/\1[success=2 default=ignore] \2/" "/etc/pam.d/common-auth"
    else
        LAST_MATCH_LINE=$(grep -nP "# here are the per-package modules" "/etc/pam.d/common-auth" | tail -n 1 | cut -d: -f 1)
        if [ ! -z $LAST_MATCH_LINE ]; then
            sed -i --follow-symlinks $LAST_MATCH_LINE" a auth     [success=2 default=ignore]    pam_pkcs11.so" "/etc/pam.d/common-auth"
        else
            echo "auth    [success=2 default=ignore]    pam_pkcs11.so" >> "/etc/pam.d/common-auth"
        fi
    fi
fi
# Check the option
if ! grep -qP "^\s*auth\s+\[success=2 default=ignore\]\s+pam_pkcs11.so\s*.*\s\b" "/etc/pam.d/common-auth"; then
    sed -i -E --follow-symlinks "/\s*auth\s+\[success=2 default=ignore\]\s+pam_pkcs11.so.*/ s/$/ /" "/etc/pam.d/common-auth"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010033
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - smartcard_pam_enabled

- name: Enable Smart Card Logins in PAM - Gather List of Packages
  ansible.builtin.package_facts:
    manager: auto
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010033
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - smartcard_pam_enabled

- name: Enable Smart Card Logins in PAM - Check to See if 'pam_pkcs11' Module Is Configured
    in '/etc/pam.d/common-auth'
  ansible.builtin.shell: grep -E '^\s*auth\s+\S+\s+pam_pkcs11\.so' /etc/pam.d/common-auth
    || true
  register: check_pam_pkcs11_module_result
  changed_when: false
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpam-pkcs11" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010033
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - smartcard_pam_enabled

- name: Enable Smart Card Logins in PAM - Configure 'pam_pkcs11' Module in '/etc/pam.d/common-auth'
  ansible.builtin.lineinfile:
    path: /etc/pam.d/common-auth
    line: auth [success=2 default=ignore] pam_pkcs11.so
    insertafter: ^\s*#
    state: present
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpam-pkcs11" in ansible_facts.packages'
  - '"pam_pkcs11.so" not in check_pam_pkcs11_module_result.stdout'
  tags:
  - DISA-STIG-UBTU-20-010033
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - smartcard_pam_enabled

- name: Enable Smart Card Logins in PAM - Ensure 'pam_pkcs11' Module Has [success=2
    default=ignore] Control Flag
  ansible.builtin.lineinfile:
    path: /etc/pam.d/common-auth
    regexp: ^(\s*auth\s+)\S+(\s+pam_pkcs11\.so.*)
    line: \g<1>[success=2 default=ignore]\g<2>
    backrefs: true
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpam-pkcs11" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010033
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - smartcard_pam_enabled

Rule   Verify that 'use_mappers' is set to 'pwent' in PAM   [ref]

The operating system must map the authenticated identity to the user or group account for PKI-based authentication. Verify that use_mappers is set to pwent in /etc/pam_pkcs11/pam_pkcs11.conf file with the following command:
$ grep ^use_mappers /etc/pam_pkcs11/pam_pkcs11.conf

use_mappers = pwent
Rationale:
Without mapping the certificate used to authenticate to the user account, the ability to determine the identity of the individual user or group will not be available for forensic analysis.
Severity: 
low
Rule ID:xccdf_org.ssgproject.content_rule_verify_use_mappers
References:
disaCCI-000187
os-srgSRG-OS-000068-GPOS-00036
stigidUBTU-20-010006
stigrefSV-238201r832933_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

if [ -e "/etc/pam_pkcs11/pam_pkcs11.conf" ] ; then
    
    LC_ALL=C sed -i "/^\s*use_mappers = pwent/Id" "/etc/pam_pkcs11/pam_pkcs11.conf"
else
    touch "/etc/pam_pkcs11/pam_pkcs11.conf"
fi
# make sure file has newline at the end
sed -i -e '$a\' "/etc/pam_pkcs11/pam_pkcs11.conf"

cp "/etc/pam_pkcs11/pam_pkcs11.conf" "/etc/pam_pkcs11/pam_pkcs11.conf.bak"
# Insert at the end of the file
printf '%s\n' "use_mappers = pwent" >> "/etc/pam_pkcs11/pam_pkcs11.conf"
# Clean up after ourselves.
rm "/etc/pam_pkcs11/pam_pkcs11.conf.bak"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010006
  - low_complexity
  - low_disruption
  - low_severity
  - no_reboot_needed
  - restrict_strategy
  - verify_use_mappers

- name: Verify that 'use_mappers' is set to 'pwent' in PAM
  lineinfile:
    path: /etc/pam_pkcs11/pam_pkcs11.conf
    create: true
    regexp: ''
    line: use_mappers = pwent
    state: present
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010006
  - low_complexity
  - low_disruption
  - low_severity
  - no_reboot_needed
  - restrict_strategy
  - verify_use_mappers

Rule   Disable Ctrl-Alt-Del Reboot Activation   [ref]

By default, SystemD will reboot the system if the Ctrl-Alt-Del key sequence is pressed.

To configure the system to ignore the Ctrl-Alt-Del key sequence from the command line instead of rebooting the system, do either of the following:
ln -sf /dev/null /etc/systemd/system/ctrl-alt-del.target
or
systemctl mask ctrl-alt-del.target


Do not simply delete the /usr/lib/systemd/system/ctrl-alt-del.service file, as this file may be restored during future system updates.
Rationale:
A locally logged-in user who presses Ctrl-Alt-Del, when at the console, can reboot the system. If accidentally pressed, as could happen in the case of mixed OS environment, this can create the risk of short-term loss of availability of systems due to unintentional reboot.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_disable_ctrlaltdel_reboot
References:
cis-csc12, 13, 14, 15, 16, 18, 3, 5
cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
cui3.4.5
disaCCI-000366, CCI-002235
hipaa164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii)
isa-62443-20094.3.3.7.3
isa-62443-2013SR 2.1, SR 5.2
iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
nistCM-6(a), AC-6(1)
nist-csfPR.AC-4, PR.DS-5
osppFAU_GEN.1.2
os-srgSRG-OS-000324-GPOS-00125, SRG-OS-000480-GPOS-00227
stigidUBTU-20-010460
stigrefSV-238380r832974_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

if [[ "$OSCAP_BOOTC_BUILD" == "YES" ]] ; then
    systemctl disable ctrl-alt-del.target
    systemctl mask ctrl-alt-del.target
else
    systemctl disable --now ctrl-alt-del.target
    systemctl mask --now ctrl-alt-del.target
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:disable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010460
  - NIST-800-171-3.4.5
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-6(a)
  - disable_ctrlaltdel_reboot
  - disable_strategy
  - high_severity
  - low_complexity
  - low_disruption
  - no_reboot_needed

- name: Disable Ctrl-Alt-Del Reboot Activation
  systemd:
    name: ctrl-alt-del.target
    force: true
    masked: true
    state: stopped
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010460
  - NIST-800-171-3.4.5
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-6(a)
  - disable_ctrlaltdel_reboot
  - disable_strategy
  - high_severity
  - low_complexity
  - low_disruption
  - no_reboot_needed
Group   Protect Accounts by Restricting Password-Based Login   Group contains 4 groups and 10 rules
[ref]   Conventionally, Unix shell accounts are accessed by providing a username and password to a login program, which tests these values for correctness using the /etc/passwd and /etc/shadow files. Password-based login is vulnerable to guessing of weak passwords, and to sniffing and man-in-the-middle attacks against passwords entered over a network or at an insecure console. Therefore, mechanisms for accessing accounts by entering usernames and passwords should be restricted to those which are operationally necessary.
Group   Set Account Expiration Parameters   Group contains 3 rules

Rule   Policy Requires Immediate Change of Temporary Passwords   [ref]

Temporary passwords for Ubuntu 20.04 operating system logons must require an immediate change to a permanent password. Verify that a policy exists that ensures when a user is created, it is creating using a method that forces a user to change their password upon their next login.
Rationale:
Without providing this capability, an account may be created without a password. Nonrepudiation cannot be guaranteed once an account is created if a user is not forced to change the temporary password upon initial logon. Temporary passwords are typically used to allow access when new accounts are created or passwords are changed. It is common practice for administrators to create temporary passwords for user accounts that allow the users to log on, yet force them to change the password once they have successfully authenticated.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_policy_temp_passwords_immediate_change
References:
disaCCI-002041
os-srgSRG-OS-000380-GPOS-00165
stigidUBTU-20-010440
stigrefSV-238361r853436_rule
Group   Set Password Expiration Parameters   Group contains 2 rules
[ref]   The file /etc/login.defs controls several password-related settings. Programs such as passwd, su, and login consult /etc/login.defs to determine behavior with regard to password aging, expiration warnings, and length. See the man page login.defs(5) for more information.

Users should be forced to change their passwords, in order to decrease the utility of compromised passwords. However, the need to change passwords often should be balanced against the risk that users will reuse or write down passwords if forced to change them too often. Forcing password changes every 90-360 days, depending on the environment, is recommended. Set the appropriate value as PASS_MAX_DAYS and apply it to existing accounts with the -M flag.

The PASS_MIN_DAYS (-m) setting prevents password changes for 7 days after the first change, to discourage password cycling. If you use this setting, train users to contact an administrator for an emergency password change in case a new password becomes compromised. The PASS_WARN_AGE (-W) setting gives users 7 days of warnings at login time that their passwords are about to expire.

For example, for each existing human user USER, expiration parameters could be adjusted to a 180 day maximum password age, 7 day minimum password age, and 7 day warning period with the following command:
$ sudo chage -M 180 -m 7 -W 7 USER
Group   Verify Proper Storage and Existence of Password Hashes   Group contains 4 rules
[ref]   By default, password hashes for local accounts are stored in the second field (colon-separated) in /etc/shadow. This file should be readable only by processes running with root credentials, preventing users from casually accessing others' password hashes and attempting to crack them. However, it remains possible to misconfigure the system and store password hashes in world-readable files such as /etc/passwd, or to even store passwords themselves in plaintext on the system. Using system-provided tools for password change/creation should allow administrators to avoid such misconfiguration.

Rule   Ensure sudo group has only necessary members   [ref]

Developers and implementers can increase the assurance in security functions by employing well-defined security policy models; structured, disciplined, and rigorous hardware and software development techniques; and sound system/security engineering principles. Implementation may include isolation of memory space and libraries. The Ubuntu operating system restricts access to security functions through the use of access control mechanisms and by implementing least privilege capabilities.
Warning:  Due to the risk of removing user rights, automated remediation is not available for this configuration check.
Rationale:
Any users assigned to the sudo group would be granted administrator access to the system.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_ensure_sudo_group_restricted
References:
disaCCI-001084
os-srgSRG-OS-000134-GPOS-00068
stigidUBTU-20-010012
stigrefSV-238206r653793_rule

Rule   Ensure no duplicate UIDs exist   [ref]

Although the useradd program will not let you create a duplicate User ID (UID), it is possible for an administrator to manually edit the /etc/passwd file and change the UID field. Users must be assigned unique UIDs for accountability and to ensure appropriate access protections.
Warning:  Due to the risk of removing user accounts or changing user's UIDS, automated remediation is not available for this configuration check.
Rationale:
Users must be assigned unique UIDs for accountability and to ensure appropriate access protections.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_no_duplicate_uids
References:
disaCCI-000764, CCI-000804
os-srgSRG-OS-000104-GPOS-00051, SRG-OS-000121-GPOS-00062
stigidUBTU-20-010010
cis6.2.13
stigrefSV-238205r653790_rule

Rule   Prevent Login to Accounts With Empty Password   [ref]

If an account is configured for password authentication but does not have an assigned password, it may be possible to log into the account without authentication. Remove any instances of the nullok in /etc/pam.d/common-password to prevent logins with empty passwords.
Warning:  If the system relies on authselect tool to manage PAM settings, the remediation will also use authselect tool. However, if any manual modification was made in PAM files, the authselect integrity check will fail and the remediation will be aborted in order to preserve intentional changes. In this case, an informative message will be shown in the remediation report. Note that this rule is not applicable for systems running within a container. Having user with empty password within a container is not considered a risk, because it should not be possible to directly login into a container anyway.
Rationale:
If an account has an empty password, anyone could log in and run commands with the privileges of that account. Accounts with empty passwords should never be used in operational environments.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_no_empty_passwords
References:
cis-csc1, 12, 13, 14, 15, 16, 18, 3, 5
cjis5.5.2
cobit5APO01.06, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.02, DSS06.03, DSS06.10
cui3.1.1, 3.1.5
disaCCI-000366
hipaa164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii)
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 5.2
iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.18.1.4, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5
nistIA-5(1)(a), IA-5(c), CM-6(a)
nist-csfPR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.DS-5
osppFIA_UAU.1
pcidssReq-8.2.3
os-srgSRG-OS-000480-GPOS-00227
stigidUBTU-20-010463
cis6.2.1
pcidss48.3.1, 8.3
stigrefSV-251504r832977_rule

Complexity:low
Disruption:medium
Reboot:false
Strategy:configure
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q installed; then

conf_name=cac_unix
conf_path="/usr/share/pam-configs"

if [ ! -f "$conf_path"/"$conf_name" ]; then
    if [ -f "$conf_path"/unix ]; then
        if grep -q "$(md5sum "$conf_path"/unix | cut -d ' ' -f 1)" /var/lib/dpkg/info/libpam-runtime.md5sums;then
            cp "$conf_path"/unix "$conf_path"/"$conf_name"
            sed -i '/Default: yes/a Priority: 257\
Conflicts: unix' "$conf_path"/"$conf_name"
            DEBIAN_FRONTEND=noninteractive pam-auth-update
        else
            echo "Not applicable - checksum of $conf_path/unix does not match the original." >&2
        fi
    else
        echo "Not applicable - $conf_path/unix does not exist" >&2
    fi
fi
config_file="/usr/share/pam-configs/cac_unix"
sed -i -E '/^Password:/,/^[^[:space:]]/ {
    /pam_unix\.so/ {
        s/\s*nullok//g
    }
}' "$config_file"

sed -i -E '/^Password-Initial:/,/^[^[:space:]]/ {
    /pam_unix\.so/ {
        s/\s*nullok//g
    }
}' "$config_file"

DEBIAN_FRONTEND=noninteractive pam-auth-update

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:medium
Reboot:false
Strategy:configure
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.5.2
  - DISA-STIG-UBTU-20-010463
  - NIST-800-171-3.1.1
  - NIST-800-171-3.1.5
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.1
  - configure_strategy
  - high_severity
  - low_complexity
  - medium_disruption
  - no_empty_passwords
  - no_reboot_needed

- name: Prevent Login to Accounts With Empty Password - Check if system relies on
    authselect
  ansible.builtin.stat:
    path: /usr/bin/authselect
  register: result_authselect_present
  when: '"libpam-runtime" in ansible_facts.packages'
  tags:
  - CJIS-5.5.2
  - DISA-STIG-UBTU-20-010463
  - NIST-800-171-3.1.1
  - NIST-800-171-3.1.5
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.1
  - configure_strategy
  - high_severity
  - low_complexity
  - medium_disruption
  - no_empty_passwords
  - no_reboot_needed

- name: Prevent Login to Accounts With Empty Password - Remediate using authselect
  block:

  - name: Prevent Login to Accounts With Empty Password - Check integrity of authselect
      current profile
    ansible.builtin.command:
      cmd: authselect check
    register: result_authselect_check_cmd
    changed_when: false
    failed_when: false

  - name: Prevent Login to Accounts With Empty Password - Informative message based
      on the authselect integrity check result
    ansible.builtin.assert:
      that:
      - result_authselect_check_cmd.rc == 0
      fail_msg:
      - authselect integrity check failed. Remediation aborted!
      - This remediation could not be applied because an authselect profile was not
        selected or the selected profile is not intact.
      - It is not recommended to manually edit the PAM files when authselect tool
        is available.
      - In cases where the default authselect profile does not cover a specific demand,
        a custom authselect profile is recommended.
      success_msg:
      - authselect integrity check passed

  - name: Prevent Login to Accounts With Empty Password - Get authselect current features
    ansible.builtin.shell:
      cmd: authselect current | tail -n+3 | awk '{ print $2 }'
    register: result_authselect_features
    changed_when: false
    when:
    - result_authselect_check_cmd is success

  - name: Prevent Login to Accounts With Empty Password - Ensure "without-nullok"
      feature is enabled using authselect tool
    ansible.builtin.command:
      cmd: authselect enable-feature without-nullok
    register: result_authselect_enable_feature_cmd
    when:
    - result_authselect_check_cmd is success
    - result_authselect_features.stdout is not search("without-nullok")

  - name: Prevent Login to Accounts With Empty Password - Ensure authselect changes
      are applied
    ansible.builtin.command:
      cmd: authselect apply-changes -b
    when:
    - result_authselect_enable_feature_cmd is not skipped
    - result_authselect_enable_feature_cmd is success
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - result_authselect_present.stat.exists
  tags:
  - CJIS-5.5.2
  - DISA-STIG-UBTU-20-010463
  - NIST-800-171-3.1.1
  - NIST-800-171-3.1.5
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.1
  - configure_strategy
  - high_severity
  - low_complexity
  - medium_disruption
  - no_empty_passwords
  - no_reboot_needed

- name: Prevent Login to Accounts With Empty Password - Remediate directly editing
    PAM files
  ansible.builtin.replace:
    dest: '{{ item }}'
    regexp: nullok
  loop:
  - /etc/pam.d/common-password
  when:
  - '"libpam-runtime" in ansible_facts.packages'
  - not result_authselect_present.stat.exists
  tags:
  - CJIS-5.5.2
  - DISA-STIG-UBTU-20-010463
  - NIST-800-171-3.1.1
  - NIST-800-171-3.1.5
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(a)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.3
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.1
  - configure_strategy
  - high_severity
  - low_complexity
  - medium_disruption
  - no_empty_passwords
  - no_reboot_needed

Rule   Ensure There Are No Accounts With Blank or Null Passwords   [ref]

Check the "/etc/shadow" file for blank passwords with the following command:
$ sudo awk -F: '!$2 {print $1}' /etc/shadow
If the command returns any results, this is a finding. Configure all accounts on the system to have a password or lock the account with the following commands: Perform a password reset:
$ sudo passwd [username]
Lock an account:
$ sudo passwd -l [username]
Warning:  Note that this rule is not applicable for systems running within a container. Having user with empty password within a container is not considered a risk, because it should not be possible to directly login into a container anyway.
Rationale:
If an account has an empty password, anyone could log in and run commands with the privileges of that account. Accounts with empty passwords should never be used in operational environments.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_no_empty_passwords_etc_shadow
References:
disaCCI-000366
nistCM-6(b), CM-6.1(iv)
os-srgSRG-OS-000480-GPOS-00227
stigidUBTU-20-010462
pcidss42.2.2, 2.2
stigrefSV-251503r808506_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

readarray -t users_with_empty_pass < <(sudo awk -F: '!$2 {print $1}' /etc/shadow)

for user_with_empty_pass in "${users_with_empty_pass[@]}"
do
    passwd -l $user_with_empty_pass
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010462
  - NIST-800-53-CM-6(b)
  - NIST-800-53-CM-6.1(iv)
  - PCI-DSSv4-2.2
  - PCI-DSSv4-2.2.2
  - high_severity
  - low_complexity
  - low_disruption
  - no_empty_passwords_etc_shadow
  - no_reboot_needed
  - restrict_strategy

- name: Collect users with no password
  command: |
    awk -F: '!$2 {print $1}' /etc/shadow
  register: users_nopasswd
  changed_when: false
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010462
  - NIST-800-53-CM-6(b)
  - NIST-800-53-CM-6.1(iv)
  - PCI-DSSv4-2.2
  - PCI-DSSv4-2.2.2
  - high_severity
  - low_complexity
  - low_disruption
  - no_empty_passwords_etc_shadow
  - no_reboot_needed
  - restrict_strategy

- name: Lock users with no password
  command: |
    passwd -l {{ item }}
  with_items: '{{ users_nopasswd.stdout_lines }}'
  when:
  - '"linux-base" in ansible_facts.packages'
  - users_nopasswd is not skipped and users_nopasswd.stdout_lines | length > 0
  tags:
  - DISA-STIG-UBTU-20-010462
  - NIST-800-53-CM-6(b)
  - NIST-800-53-CM-6.1(iv)
  - PCI-DSSv4-2.2
  - PCI-DSSv4-2.2.2
  - high_severity
  - low_complexity
  - low_disruption
  - no_empty_passwords_etc_shadow
  - no_reboot_needed
  - restrict_strategy
Group   Restrict Root Logins   Group contains 1 rule
[ref]   Direct root logins should be allowed only for emergency use. In normal situations, the administrator should access the system via a unique unprivileged account, and then use su or sudo to execute privileged commands. Discouraging administrators from accessing the root account directly ensures an audit trail in organizations with multiple administrators. Locking down the channels through which root can connect directly also reduces opportunities for password-guessing against the root account. The login program uses the file /etc/securetty to determine which interfaces should allow root logins. The virtual devices /dev/console and /dev/tty* represent the system consoles (accessible via the Ctrl-Alt-F1 through Ctrl-Alt-F6 keyboard sequences on a default installation). The default securetty file also contains /dev/vc/*. These are likely to be deprecated in most environments, but may be retained for compatibility. Root should also be prohibited from connecting via network protocols. Other sections of this document include guidance describing how to prevent root from logging in via SSH.

Rule   Direct root Logins Are Not Allowed   [ref]

Configure the operating system to prevent direct logins to the root account by performing the following operations:
$ sudo passwd -l root
Rationale:
Disabling direct root logins ensures proper accountability and multifactor authentication to privileged accounts.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_prevent_direct_root_logins
References:
disaCCI-000770, CCI-004045
os-srgSRG-OS-000109-GPOS-00056
stigidUBTU-20-010408
stigrefSV-238329r654162_rule
Group   Secure Session Configuration Files for Login Accounts   Group contains 1 group and 3 rules
[ref]   When a user logs into a Unix account, the system configures the user's session by reading a number of files. Many of these files are located in the user's home directory, and may have weak permissions as a result of user error or misconfiguration. If an attacker can modify or even read certain types of account configuration information, they can often gain full access to the affected user's account. Therefore, it is important to test and correct configuration file permissions for interactive accounts, particularly those of privileged users such as root or system administrators.
Group   Ensure that Users Have Sensible Umask Values   Group contains 1 rule
[ref]   The umask setting controls the default permissions for the creation of new files. With a default umask setting of 077, files and directories created by users will not be readable by any other user on the system. Users who wish to make specific files group- or world-readable can accomplish this by using the chmod command. Additionally, users can make all their files readable to their group by default by setting a umask of 027 in their shell configuration files. If default per-user groups exist (that is, if every user has a default group whose name is the same as that user's username and whose only member is the user), then it may even be safe for users to select a umask of 007, making it very easy to intentionally share files with groups of which the user is a member.

Rule   Set Interactive Session Timeout   [ref]

Setting the TMOUT option in /etc/profile ensures that all user sessions will terminate based on inactivity. The value of TMOUT should be exported and read only. The TMOUT setting in a file loaded by /etc/profile, e.g. /etc/profile.d/tmout.sh should read as follows:
TMOUT=600
        
readonly TMOUT export TMOUT
Rationale:
Terminating an idle session within a short time period reduces the window of opportunity for unauthorized personnel to take control of a management session enabled on the console or console port that has been left unattended.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_tmout
References:
cis-csc1, 12, 15, 16
cobit5DSS05.04, DSS05.10, DSS06.10
cui3.1.11
disaCCI-000057, CCI-001133
isa-62443-20094.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9
isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9
iso27001-2013A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3
nerc-cipCIP-004-6 R2.2.3, CIP-007-3 R5.1, CIP-007-3 R5.2, CIP-007-3 R5.3.1, CIP-007-3 R5.3.2, CIP-007-3 R5.3.3
nistAC-12, SC-10, AC-2(5), CM-6(a)
nist-csfPR.AC-7
os-srgSRG-OS-000163-GPOS-00072, SRG-OS-000029-GPOS-00010
stigidUBTU-20-010013
cis5.4.5
anssiR32
pcidss48.6.1, 8.6
stigrefSV-238207r853404_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

var_accounts_tmout='600'


# if 0, no occurence of tmout found, if 1, occurence found
tmout_found=0

for f in /etc/bash.bashrc /etc/profile /etc/profile.d/*.sh; do
    if grep --silent '^\s*TMOUT' $f; then
        sed -i -E "s/^(\s*)TMOUT\s*=\s*(\w|\$)*(.*)$/\1TMOUT=$var_accounts_tmout\3/g" $f
        tmout_found=1
        if ! grep --silent '^\s*readonly TMOUT' $f ; then
            echo "readonly TMOUT" >> $f
        fi
        if ! grep --silent '^\s*export TMOUT' $f ; then
            echo "export TMOUT" >> $f
        fi
    fi
done

if [ $tmout_found -eq 0 ]; then
        echo -e "\n# Set TMOUT to $var_accounts_tmout per security requirements" >> /etc/profile.d/tmout.sh
        echo "TMOUT=$var_accounts_tmout" >> /etc/profile.d/tmout.sh
        echo "readonly TMOUT" >> /etc/profile.d/tmout.sh
        echo "export TMOUT" >> /etc/profile.d/tmout.sh
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010013
  - NIST-800-171-3.1.11
  - NIST-800-53-AC-12
  - NIST-800-53-AC-2(5)
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SC-10
  - PCI-DSSv4-8.6
  - PCI-DSSv4-8.6.1
  - accounts_tmout
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
- name: XCCDF Value var_accounts_tmout # promote to variable
  set_fact:
    var_accounts_tmout: !!str 600
  tags:
    - always

- name: Correct any occurrence of TMOUT in /etc/profile
  replace:
    path: /etc/profile
    regexp: ^[^#].*TMOUT=.*
    replace: typeset -xr TMOUT={{ var_accounts_tmout }}
  register: profile_replaced
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010013
  - NIST-800-171-3.1.11
  - NIST-800-53-AC-12
  - NIST-800-53-AC-2(5)
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SC-10
  - PCI-DSSv4-8.6
  - PCI-DSSv4-8.6.1
  - accounts_tmout
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy

- name: Set Interactive Session Timeout
  lineinfile:
    path: /etc/profile.d/tmout.sh
    create: true
    regexp: TMOUT=
    line: typeset -xr TMOUT={{ var_accounts_tmout }}
    state: present
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010013
  - NIST-800-171-3.1.11
  - NIST-800-53-AC-12
  - NIST-800-53-AC-2(5)
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SC-10
  - PCI-DSSv4-8.6
  - PCI-DSSv4-8.6.1
  - accounts_tmout
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
Group   AppArmor   Group contains 2 rules
[ref]   Many security vulnerabilities result from bugs in trusted programs. A trusted program runs with privileges that attackers want to possess. The program fails to keep that trust if there is a bug in the program that allows the attacker to acquire said privilege.

AppArmor® is an application security solution designed specifically to apply privilege confinement to suspect programs. AppArmor allows the administrator to specify the domain of activities the program can perform by developing a security profile. A security profile is a listing of files that the program may access and the operations the program may perform. AppArmor secures applications by enforcing good application behavior without relying on attack signatures, so it can prevent attacks even if previously unknown vulnerabilities are being exploited.

Rule   Ensure AppArmor is installed   [ref]

AppArmor provide Mandatory Access Controls.
Rationale:
Without a Mandatory Access Control system installed only the default Discretionary Access Control system will be available.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_package_apparmor_installed
References:
disaCCI-001764, CCI-001774, CCI-002165, CCI-002235
os-srgSRG-OS-000368-GPOS-00154, SRG-OS-000312-GPOS-00122, SRG-OS-000312-GPOS-00123, SRG-OS-000312-GPOS-00124, SRG-OS-000324-GPOS-00125, SRG-OS-000370-GPOS-00155
stigidUBTU-20-010439
cis1.7.1.1
anssiR45
stigrefSV-238360r853435_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then

DEBIAN_FRONTEND=noninteractive apt-get install -y "apparmor"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


[[packages]]
name = "apparmor"
version = "*"

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
- name: Ensure apparmor is installed
  package:
    name: apparmor
    state: present
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
  - DISA-STIG-UBTU-20-010439
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - package_apparmor_installed

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
include install_apparmor

class install_apparmor {
  package { 'apparmor':
    ensure => 'installed',
  }
}

Rule   Ensure AppArmor is Active and Configured   [ref]

Verify that the Apparmor tool is configured to control whitelisted applications and user home directory access control.

The apparmor service can be enabled with the following command:
$ sudo systemctl enable apparmor.service
Rationale:
Using a whitelist provides a configuration management method for allowing the execution of only authorized software. Using only authorized software decreases risk by limiting the number of potential vulnerabilities.

The organization must identify authorized software programs and permit execution of authorized software by adding each authorized program to the "pam_apparmor" exception policy. The process used to identify software programs that are authorized to execute on organizational information systems is commonly referred to as whitelisting.

Verification of whitelisted software occurs prior to execution or at system startup.

Users' home directories/folders may contain information of a sensitive nature. Nonprivileged users should coordinate any sharing of information with a System Administrator (SA) through shared resources.

Apparmor can confine users to their home directory, not allowing them to make any changes outside of their own home directories. Confining users to their home directory will minimize the risk of sharing information.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_apparmor_configured
References:
disaCCI-001764, CCI-001774, CCI-002165, CCI-002233, CCI-002235
nistAC-3(4), AC-6(8), AC-6(10), CM-7(5)(b), CM-7(2), SC-7(21), CM-6(a)
os-srgSRG-OS-000312-GPOS-00122, SRG-OS-000312-GPOS-00123, SRG-OS-000312-GPOS-00124, SRG-OS-000324-GPOS-00125, SRG-OS-000326-GPOS-00126, SRG-OS-000370-GPOS-00155, SRG-OS-000480-GPOS-00230, SRG-OS-000480-GPOS-00227, SRG-OS-000480-GPOS-00231, SRG-OS-000480-GPOS-00232
stigidUBTU-20-010439
anssiR45
stigrefSV-238360r853435_rule

# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then

# Enable apparmor
/usr/bin/systemctl enable "apparmor"
/usr/bin/systemctl start "apparmor"
# The service may not be running because it has been started and failed,
# so let's reset the state so OVAL checks pass.
# Service should be 'inactive', not 'failed' after reboot though.
if /usr/bin/systemctl --failed | grep -q "apparmor"; then
    /usr/bin/systemctl reset-failed "apparmor"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


[customizations.services]
enabled = ["apparmor"]

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
include enable_apparmor

class enable_apparmor {
  service {'apparmor':
    enable => true,
    ensure => 'running',
  }
}
Group   GRUB2 bootloader configuration   Group contains 2 groups and 2 rules
[ref]   During the boot process, the boot loader is responsible for starting the execution of the kernel and passing options to it. The boot loader allows for the selection of different kernels - possibly on different partitions or media. The default Ubuntu 20.04 boot loader for x86 systems is called GRUB2. Options it can pass to the kernel include single-user mode, which provides root access without any authentication, and the ability to disable SELinux. To prevent local users from modifying the boot parameters and endangering security, protect the boot loader configuration with a password and ensure its configuration file's permissions are set properly.
Group   Non-UEFI GRUB2 bootloader configuration   Group contains 1 rule
[ref]   Non-UEFI GRUB2 bootloader configuration

Rule   Set Boot Loader Password in grub2   [ref]

The grub2 boot loader should have a superuser account and password protection enabled to protect boot-time settings.

Since plaintext passwords are a security risk, generate a hash for the password by running the following command:
# grub2-mkpasswd-pbkdf2
When prompted, enter the password that was selected.

Using the hash from the output, modify the /etc/grub.d/40_custom file with the following content:
set superusers="boot"
password_pbkdf2 boot grub.pbkdf2.sha512.VeryLongString
NOTE: the bootloader superuser account and password MUST differ from the root account and password. Once the superuser password has been added, update the grub.cfg file by running:
update-grub 
Warning:  To prevent hard-coded passwords, automatic remediation of this control is not available. Remediation must be automated as a component of machine provisioning, or followed manually as outlined above. Also, do NOT manually add the superuser account and password to the grub.cfg file as the grub2-mkconfig command overwrites this file.
Rationale:
Password protection on the boot loader configuration ensures users with physical access cannot trivially alter important bootloader settings. These include which kernel to use, and whether to enter single-user mode.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_grub2_password
References:
cis-csc1, 11, 12, 14, 15, 16, 18, 3, 5
cobit5DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.06, DSS06.10
cui3.4.5
disaCCI-000213
hipaa164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii)
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4
isa-62443-2013SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7
iso27001-2013A.18.1.4, A.6.1.2, A.7.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5
nistCM-6(a)
nist-csfPR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.PT-3
os-srgSRG-OS-000080-GPOS-00048
stigidUBTU-20-010009
cis1.5.1
anssiR5
stigrefSV-238204r832936_rule
Group   UEFI GRUB2 bootloader configuration   Group contains 1 rule
[ref]   UEFI GRUB2 bootloader configuration
Warning:  UEFI generally uses vfat file systems, which does not support Unix-style permissions managed by chmod command. In this case, in order to change file permissions for files within /boot/efi it is necessary to update the mount options in /etc/fstab file and reboot the system.

Rule   Set the UEFI Boot Loader Password   [ref]

The grub2 boot loader should have a superuser account and password protection enabled to protect boot-time settings.

Since plaintext passwords are a security risk, generate a hash for the password by running the following command:
# grub2-mkpasswd-pbkdf2
When prompted, enter the password that was selected.

Using the hash from the output, modify the /etc/grub.d/40_custom file with the following content:
set superusers="boot"
password_pbkdf2 boot grub.pbkdf2.sha512.VeryLongString
NOTE: the bootloader superuser account and password MUST differ from the root account and password. Once the superuser password has been added, update the grub.cfg file by running:
update-grub 
Warning:  To prevent hard-coded passwords, automatic remediation of this control is not available. Remediation must be automated as a component of machine provisioning, or followed manually as outlined above. Also, do NOT manually add the superuser account and password to the grub.cfg file as the grub2-mkconfig command overwrites this file.
Rationale:
Password protection on the boot loader configuration ensures users with physical access cannot trivially alter important bootloader settings. These include which kernel to use, and whether to enter single-user mode.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_grub2_uefi_password
References:
cis-csc11, 12, 14, 15, 16, 18, 3, 5
cobit5DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS06.03, DSS06.06
cui3.4.5
disaCCI-000213
hipaa164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii)
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4
isa-62443-2013SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7
iso27001-2013A.6.1.2, A.7.1.1, A.9.1.2, A.9.2.1, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
nistCM-6(a)
nist-csfPR.AC-4, PR.AC-6, PR.PT-3
osppFIA_UAU.1
os-srgSRG-OS-000080-GPOS-00048
stigidUBTU-20-010009
cis1.5.1
anssiR5
stigrefSV-238204r832936_rule
Group   Configure Syslog   Group contains 1 group and 3 rules
[ref]   The syslog service has been the default Unix logging mechanism for many years. It has a number of downsides, including inconsistent log format, lack of authentication for received messages, and lack of authentication, encryption, or reliable transport for messages sent over a network. However, due to its long history, syslog is a de facto standard which is supported by almost all Unix applications.

In Ubuntu 20.04, rsyslog has replaced ksyslogd as the syslog daemon of choice, and it includes some additional security features such as reliable, connection-oriented (i.e. TCP) transmission of logs, the option to log to database formats, and the encryption of log data en route to a central logging server. This section discusses how to configure rsyslog for best effect, and how to use tools provided with the system to maintain and monitor logs.
Group   Ensure Proper Configuration of Log Files   Group contains 1 rule
[ref]   The file /etc/rsyslog.conf controls where log message are written. These are controlled by lines called rules, which consist of a selector and an action. These rules are often customized depending on the role of the system, the requirements of the environment, and whatever may enable the administrator to most effectively make use of log data. The default rules in Ubuntu 20.04 are:
*.info;mail.none;authpriv.none;cron.none                /var/log/messages
authpriv.*                                              /var/log/secure
mail.*                                                  -/var/log/maillog
cron.*                                                  /var/log/cron
*.emerg                                                 *
uucp,news.crit                                          /var/log/spooler
local7.*                                                /var/log/boot.log
See the man page rsyslog.conf(5) for more information. Note that the rsyslog daemon can be configured to use a timestamp format that some log processing programs may not understand. If this occurs, edit the file /etc/rsyslog.conf and add or edit the following line:
$ ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

Rule   Ensure remote access methods are monitored in Rsyslog   [ref]

Logging of remote access methods must be implemented to help identify cyber attacks and ensure ongoing compliance with remote access policies are being audited and upheld. An examples of a remote access method is the use of the Remote Desktop Protocol (RDP) from an external, non-organization controlled network. The /etc/rsyslog.conf or /etc/rsyslog.d/*.conf file should contain a match for the following selectors: auth.*, authpriv.*, and daemon.*. If not, use the following as an example configuration: auth.*;authpriv.* /var/log/secure daemon.* /var/log/messages
Rationale:
Logging remote access methods can be used to trace the decrease the risks associated with remote user access management. It can also be used to spot cyber attacks and ensure ongoing compliance with organizational policies surrounding the use of remote access methods.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_rsyslog_remote_access_monitoring
References:
disaCCI-000067
nistAC-17(1)
os-srgSRG-OS-000032-GPOS-00013
stigidUBTU-20-010403
stigrefSV-238324r832959_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed && dpkg-query --show --showformat='${db:Status-Status}\n' 'rsyslog' 2>/dev/null | grep -q installed; then

if [ ! -f /etc/rsyslog.d/50-default.conf ]; then
    # Something is not right, create the file
    touch /etc/rsyslog.d/50-default.conf
fi

# Check to see if auth exists
if ! grep -Erq "^auth\.\*,authpriv\.\*" /etc/rsyslog.*; then
    echo "auth.*,authpriv.* /var/log/secure" >> /etc/rsyslog.d/50-default.conf
fi

if ! grep -Erq "^daemon\.\*" /etc/rsyslog.*; then
    echo "daemon.* /var/log/messages" >> /etc/rsyslog.d/50-default.conf
fi

systemctl restart rsyslog.service

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:medium
Reboot:false
Strategy:configure
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010403
  - NIST-800-53-AC-17(1)
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - rsyslog_remote_access_monitoring

- name: Ensure remote access methods are monitored in Rsyslog - Set Facts
  ansible.builtin.set_fact:
    conf_files:
    - /etc/rsyslog.d/50-default.conf
    remote_methods:
    - selector: auth.*
      regexp: ^.*auth\.\*.*$
      log_path_name: secure
    - selector: authpriv.*
      regexp: ^.*authpriv\.\*.*$
      log_path_name: secure
    - selector: daemon.*
      regexp: ^.*daemon\.\*.*$
      log_path_name: messages
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"rsyslog" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010403
  - NIST-800-53-AC-17(1)
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - rsyslog_remote_access_monitoring

- name: Ensure remote access methods are monitored in Rsyslog - Ensure /etc/rsyslog.d/50-default.conf
    Exists
  ansible.builtin.file:
    path: '{{ conf_files.0 }}'
    state: touch
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"rsyslog" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010403
  - NIST-800-53-AC-17(1)
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - rsyslog_remote_access_monitoring

- name: Ensure remote access methods are monitored in Rsyslog - Check for Existing
    Values in Conf Files
  ansible.builtin.lineinfile:
    path: '{{ item.1 }}'
    regexp: '{{ item.0.regexp }}'
    state: absent
  check_mode: true
  changed_when: false
  register: remote_method_values
  loop: '{{ remote_methods|product(conf_files)|list }}'
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"rsyslog" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010403
  - NIST-800-53-AC-17(1)
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - rsyslog_remote_access_monitoring

- name: Ensure remote access methods are monitored in Rsyslog - Configure /etc/rsyslog.d/50-default.conf
    With Proper Log Paths
  ansible.builtin.lineinfile:
    path: /etc/rsyslog.d/50-default.conf
    line: '{{ item.item.0.selector }} /var/log/{{ item.item.0.log_path_name }}'
    insertafter: ^.*\/var\/log\/secure.*$
    create: true
  loop: '{{ remote_method_values.results }}'
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"rsyslog" in ansible_facts.packages'
  - item.found == 0
  tags:
  - DISA-STIG-UBTU-20-010403
  - NIST-800-53-AC-17(1)
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - rsyslog_remote_access_monitoring

Rule   Enable rsyslog Service   [ref]

The rsyslog service provides syslog-style logging by default on Ubuntu 20.04. The rsyslog service can be enabled with the following command:
$ sudo systemctl enable rsyslog.service
Rationale:
The rsyslog service must be running in order to provide logging services, which are essential to system administration.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_service_rsyslog_enabled
References:
cis-csc1, 12, 13, 14, 15, 16, 2, 3, 5, 6, 7, 8, 9
cobit5APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO13.01, BAI03.05, BAI04.04, DSS01.03, DSS03.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01
disaCCI-000366
hipaa164.312(a)(2)(ii)
isa-62443-20094.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4
isa-62443-2013SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 6.2, SR 7.1, SR 7.2
iso27001-2013A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.14.2.7, A.15.2.1, A.15.2.2, A.17.2.1
nistCM-6(a), AU-4(1)
nist-csfDE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.DS-4, PR.PT-1
os-srgSRG-OS-000480-GPOS-00227
stigidUBTU-20-010432
cis4.2.1.2
stigrefSV-238353r654234_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

SYSTEMCTL_EXEC='/usr/bin/systemctl'
"$SYSTEMCTL_EXEC" unmask 'rsyslog.service'
"$SYSTEMCTL_EXEC" start 'rsyslog.service'
"$SYSTEMCTL_EXEC" enable 'rsyslog.service'

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


[customizations.services]
enabled = ["rsyslog"]

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010432
  - NIST-800-53-AU-4(1)
  - NIST-800-53-CM-6(a)
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - service_rsyslog_enabled

- name: Enable rsyslog Service - Enable service rsyslog
  block:

  - name: Gather the package facts
    package_facts:
      manager: auto

  - name: Enable rsyslog Service - Enable Service rsyslog
    ansible.builtin.systemd:
      name: rsyslog
      enabled: true
      state: started
      masked: false
    when:
    - '"rsyslog" in ansible_facts.packages'
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010432
  - NIST-800-53-AU-4(1)
  - NIST-800-53-CM-6(a)
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - service_rsyslog_enabled

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
include enable_rsyslog

class enable_rsyslog {
  service {'rsyslog':
    enable => true,
    ensure => 'running',
  }
}

Rule   Ensure real-time clock is set to UTC   [ref]

Ensure that the system real-time clock (RTC) is set to Coordinated Universal Time (UTC).
Rationale:
If time stamps are not consistently applied and there is no common time reference, it is difficult to perform forensic analysis. Time stamps generated by the operating system include date and time. Time is commonly expressed in UTC, a modern continuation of GMT, or local time with an offset from UTC.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_ensure_rtc_utc_configuration
References:
disaCCI-001890
os-srgSRG-OS-000359-GPOS-00146
stigidUBTU-20-010230
stigrefSV-238308r877383_rule

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

if timedatectl status | grep -i "time zone" | grep -iv 'UTC\|GMT'; then
    timedatectl set-timezone UTC
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
Group   Network Configuration and Firewalls   Group contains 6 groups and 8 rules
[ref]   Most systems must be connected to a network of some sort, and this brings with it the substantial risk of network attack. This section discusses the security impact of decisions about networking which must be made when configuring a system.

This section also discusses firewalls, network access controls, and other network security frameworks, which allow system-level rules to be written that can limit an attackers' ability to connect to your system. These rules can specify that network traffic should be allowed or denied from certain IP addresses, hosts, and networks. The rules can also specify which of the system's network services are available to particular hosts or networks.
Group   Kernel Parameters Which Affect Networking   Group contains 1 group and 1 rule
[ref]   The sysctl utility is used to set parameters which affect the operation of the Linux kernel. Kernel parameters which affect networking and have security implications are described here.
Group   Network Related Kernel Runtime Parameters for Hosts and Routers   Group contains 1 rule
[ref]   Certain kernel parameters should be set for systems which are acting as either hosts or routers to improve the system's ability defend against certain types of IPv4 protocol attacks.

Rule   Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces   [ref]

To set the runtime status of the net.ipv4.tcp_syncookies kernel parameter, run the following command:
$ sudo sysctl -w net.ipv4.tcp_syncookies=1
To make sure that the setting is persistent, add the following line to a file in the directory /etc/sysctl.d:
net.ipv4.tcp_syncookies = 1
Rationale:
A TCP SYN flood attack can cause a denial of service by filling a system's TCP connection table with connections in the SYN_RCVD state. Syncookies can be used to track a connection when a subsequent ACK is received, verifying the initiator is attempting a valid connection and is not a flood source. This feature is activated when a flood condition is detected, and enables the system to continue servicing valid connection requests.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_sysctl_net_ipv4_tcp_syncookies
References:
cis-csc1, 12, 13, 14, 15, 16, 18, 2, 4, 6, 7, 8, 9
cjis5.10.1.1
cobit5APO01.06, APO13.01, BAI04.04, DSS01.03, DSS01.05, DSS03.01, DSS03.05, DSS05.02, DSS05.04, DSS05.07, DSS06.02
cui3.1.20
disaCCI-001095, CCI-000366, CCI-002385
isa-62443-20094.2.3.4, 4.3.3.4, 4.4.3.3
isa-62443-2013SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.2, SR 7.1, SR 7.2, SR 7.6
iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.12.1.1, A.12.1.2, A.12.1.3, A.13.1.1, A.13.1.2, A.13.1.3, A.13.2.1, A.13.2.2, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.17.2.1, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
nistCM-7(a), CM-7(b), SC-5(1), SC-5(2), SC-5(3)(a), CM-6(a)
nist-csfDE.AE-1, DE.CM-1, ID.AM-3, PR.AC-5, PR.DS-4, PR.DS-5, PR.PT-4
pcidssReq-1.4.1
os-srgSRG-OS-000480-GPOS-00227, SRG-OS-000420-GPOS-00186, SRG-OS-000142-GPOS-00071
stigidUBTU-20-010412
cis3.3.8
anssiR12
pcidss41.4.3, 1.4
stigrefSV-238333r654174_rule

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

# Comment out any occurrences of net.ipv4.tcp_syncookies from /etc/sysctl.d/*.conf files

for f in /etc/sysctl.d/*.conf /run/sysctl.d/*.conf /usr/local/lib/sysctl.d/*.conf; do


  # skip systemd-sysctl symlink (/etc/sysctl.d/99-sysctl.conf -> /etc/sysctl.conf)
  if [[ "$(readlink -f "$f")" == "/etc/sysctl.conf" ]]; then continue; fi

  matching_list=$(grep -P '^(?!#).*[\s]*net.ipv4.tcp_syncookies.*$' $f | uniq )
  if ! test -z "$matching_list"; then
    while IFS= read -r entry; do
      escaped_entry=$(sed -e 's|/|\\/|g' <<< "$entry")
      # comment out "net.ipv4.tcp_syncookies" matches to preserve user data
      sed -i --follow-symlinks "s/^${escaped_entry}$/# &/g" $f
    done <<< "$matching_list"
  fi
done

#
# Set sysctl config file which to save the desired value
#

SYSCONFIG_FILE="/etc/sysctl.conf"

sysctl_net_ipv4_tcp_syncookies_value='1'


#
# Set runtime for net.ipv4.tcp_syncookies
#
if [[ "$OSCAP_BOOTC_BUILD" != "YES" ]] ; then
    /sbin/sysctl -q -n -w net.ipv4.tcp_syncookies="$sysctl_net_ipv4_tcp_syncookies_value"
fi

#
# If net.ipv4.tcp_syncookies present in /etc/sysctl.conf, change value to appropriate value
#	else, add "net.ipv4.tcp_syncookies = value" to /etc/sysctl.conf
#

# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^net.ipv4.tcp_syncookies")

# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$sysctl_net_ipv4_tcp_syncookies_value"

# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^net.ipv4.tcp_syncookies\\>" "${SYSCONFIG_FILE}"; then
    escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
    LC_ALL=C sed -i --follow-symlinks "s/^net.ipv4.tcp_syncookies\\>.*/$escaped_formatted_output/gi" "${SYSCONFIG_FILE}"
else
    if [[ -s "${SYSCONFIG_FILE}" ]] && [[ -n "$(tail -c 1 -- "${SYSCONFIG_FILE}" || true)" ]]; then
        LC_ALL=C sed -i --follow-symlinks '$a'\\ "${SYSCONFIG_FILE}"
    fi
    printf '%s\n' "$formatted_output" >> "${SYSCONFIG_FILE}"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.10.1.1
  - DISA-STIG-UBTU-20-010412
  - NIST-800-171-3.1.20
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - NIST-800-53-SC-5(1)
  - NIST-800-53-SC-5(2)
  - NIST-800-53-SC-5(3)(a)
  - PCI-DSS-Req-1.4.1
  - PCI-DSSv4-1.4
  - PCI-DSSv4-1.4.3
  - disable_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - reboot_required
  - sysctl_net_ipv4_tcp_syncookies

- name: List /etc/sysctl.d/*.conf files
  find:
    paths:
    - /etc/sysctl.d/
    - /run/sysctl.d/
    - /usr/local/lib/sysctl.d/
    contains: ^[\s]*net.ipv4.tcp_syncookies.*$
    patterns: '*.conf'
    file_type: any
  register: find_sysctl_d
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - CJIS-5.10.1.1
  - DISA-STIG-UBTU-20-010412
  - NIST-800-171-3.1.20
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - NIST-800-53-SC-5(1)
  - NIST-800-53-SC-5(2)
  - NIST-800-53-SC-5(3)(a)
  - PCI-DSS-Req-1.4.1
  - PCI-DSSv4-1.4
  - PCI-DSSv4-1.4.3
  - disable_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - reboot_required
  - sysctl_net_ipv4_tcp_syncookies

- name: Comment out any occurrences of net.ipv4.tcp_syncookies from config files
  replace:
    path: '{{ item.path }}'
    regexp: ^[\s]*net.ipv4.tcp_syncookies
    replace: '#net.ipv4.tcp_syncookies'
  loop: '{{ find_sysctl_d.files }}'
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - CJIS-5.10.1.1
  - DISA-STIG-UBTU-20-010412
  - NIST-800-171-3.1.20
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - NIST-800-53-SC-5(1)
  - NIST-800-53-SC-5(2)
  - NIST-800-53-SC-5(3)(a)
  - PCI-DSS-Req-1.4.1
  - PCI-DSSv4-1.4
  - PCI-DSSv4-1.4.3
  - disable_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - reboot_required
  - sysctl_net_ipv4_tcp_syncookies
- name: XCCDF Value sysctl_net_ipv4_tcp_syncookies_value # promote to variable
  set_fact:
    sysctl_net_ipv4_tcp_syncookies_value: !!str 1
  tags:
    - always

- name: Ensure sysctl net.ipv4.tcp_syncookies is set
  sysctl:
    name: net.ipv4.tcp_syncookies
    value: '{{ sysctl_net_ipv4_tcp_syncookies_value }}'
    sysctl_file: /etc/sysctl.conf
    state: present
    reload: true
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - CJIS-5.10.1.1
  - DISA-STIG-UBTU-20-010412
  - NIST-800-171-3.1.20
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - NIST-800-53-SC-5(1)
  - NIST-800-53-SC-5(2)
  - NIST-800-53-SC-5(3)(a)
  - PCI-DSS-Req-1.4.1
  - PCI-DSSv4-1.4
  - PCI-DSSv4-1.4.3
  - disable_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - reboot_required
  - sysctl_net_ipv4_tcp_syncookies
Group   Uncomplicated Firewall (ufw)   Group contains 5 rules
[ref]   The Linux kernel in Ubuntu provides a packet filtering system called netfilter, and the traditional interface for manipulating netfilter are the iptables suite of commands. iptables provide a complete firewall solution that is both highly configurable and highly flexible. Becoming proficient in iptables takes time, and getting started with netfilter firewalling using only iptables can be a daunting task. As a result, many frontends for iptables have been created over the years, each trying to achieve a different result and targeting a different audience. The Uncomplicated Firewall (ufw) is a frontend for iptables and is particularly well-suited for host-based firewalls. ufw provides a framework for managing netfilter, as well as a command-line interface for manipulating the firewall. ufw aims to provide an easy to use interface for people unfamiliar with firewall concepts, while at the same time simplifies complicated iptables commands to help an administrator who knows what he or she is doing. ufw is an upstream for other distributions and graphical frontends.

Rule   Install ufw Package   [ref]

The ufw package can be installed with the following command:
$ apt-get install ufw
Rationale:
ufw controls the Linux kernel network packet filtering code. ufw allows system operators to set up firewalls and IP masquerading, etc.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_package_ufw_installed
References:
disaCCI-002314
os-srgSRG-OS-000297-GPOS-00115
stigidUBTU-20-010433
cis3.5.1.1
stigrefSV-238354r853429_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

DEBIAN_FRONTEND=noninteractive apt-get install -y "ufw"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


[[packages]]
name = "ufw"
version = "*"

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010433
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - package_ufw_installed

- name: Ensure ufw is installed
  package:
    name: ufw
    state: present
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010433
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - package_ufw_installed

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
include install_ufw

class install_ufw {
  package { 'ufw':
    ensure => 'installed',
  }
}

Rule   Verify ufw Enabled   [ref]

The ufw service can be enabled with the following command:
$ sudo systemctl enable ufw.service
Rationale:
The ufw service must be enabled and running in order for ufw to protect the system
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_service_ufw_enabled
References:
disaCCI-002314
os-srgSRG-OS-000297-GPOS-00115
stigidUBTU-20-010434
cis3.5.1.3
stigrefSV-238355r853430_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed && { ( dpkg-query --show --showformat='${db:Status-Status}\n' 'ufw' 2>/dev/null | grep -q installed && dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed ); }; then

SYSTEMCTL_EXEC='/usr/bin/systemctl'
"$SYSTEMCTL_EXEC" unmask 'ufw.service'
"$SYSTEMCTL_EXEC" start 'ufw.service'
"$SYSTEMCTL_EXEC" enable 'ufw.service'

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi


[customizations.services]
enabled = ["ufw"]

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010434
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - service_ufw_enabled

- name: Verify ufw Enabled - Enable service ufw
  block:

  - name: Gather the package facts
    package_facts:
      manager: auto

  - name: Verify ufw Enabled - Enable Service ufw
    ansible.builtin.systemd:
      name: ufw
      enabled: true
      state: started
      masked: false
    when:
    - '"ufw" in ansible_facts.packages'
  when:
  - '"linux-base" in ansible_facts.packages'
  - ( "ufw" in ansible_facts.packages and "linux-base" in ansible_facts.packages )
  tags:
  - DISA-STIG-UBTU-20-010434
  - enable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - service_ufw_enabled

Complexity:low
Disruption:low
Reboot:false
Strategy:enable
include enable_ufw

class enable_ufw {
  service {'ufw':
    enable => true,
    ensure => 'running',
  }
}

Rule   Verify ufw Active   [ref]

Verify the ufw is enabled on the system with the following command:
# sudo ufw status
If the above command returns the status as "inactive" or any type of error, this is a finding.
Rationale:
Remote access services, such as those providing remote access to network devices and information systems, which lack automated control capabilities, increase risk and make remote user access management difficult at best. Remote access is access to DOD nonpublic information systems by an authorized user (or an information system) communicating through an external, nonorganization-controlled network. Remote access methods include, for example, dial-up, broadband, and wireless. Ubuntu 22.04 LTS functionality (e.g., RDP) must be capable of taking enforcement action if the audit reveals unauthorized activity. Automated control of remote access sessions allows organizations to ensure ongoing compliance with remote access policies by enforcing connection rules of remote access applications on a variety of information system components.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_check_ufw_active
References:
disaCCI-002314
stigidUBTU-20-010434
cis3.5.1.3
stigrefSV-238355r853430_rule

Rule   Only Allow Authorized Network Services in ufw   [ref]

Check the firewall configuration for any unnecessary or prohibited functions, ports, protocols, and/or services by running the following command:
$ sudo ufw show raw
Chain OUTPUT (policy ACCEPT)
target prot opt sources destination
Chain INPUT (policy ACCEPT 1 packets, 40 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Ask the System Administrator for the site or program PPSM CLSA. Verify the services allowed by the firewall match the PPSM CLSA.
Rationale:
To prevent unauthorized connection of devices, unauthorized transfer of information, or unauthorized tunneling (i.e., embedding of data types within data types), organizations must disable or restrict unused or unnecessary physical and logical ports/protocols on information systems. Operating systems are capable of providing a wide variety of functions and services. Some of the functions and services provided by default may not be necessary to support essential organizational operations. Additionally, it is sometimes convenient to provide multiple services from a single component (e.g., VPN and IPS); however, doing so increases risk over limiting the services provided by any one component. To support the requirements and principles of least functionality, the operating system must support the organizational requirements, providing only essential capabilities and limiting the use of ports, protocols, and/or services to only those required, authorized, and approved to conduct official business or to address authorized quality of life issues.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_ufw_only_required_services
References:
disaCCI-000382
os-srgSRG-OS-000096-GPOS-00050
stigidUBTU-20-010407
stigrefSV-238328r654159_rule

Rule   ufw Must rate-limit network interfaces   [ref]

The operating system must configure the uncomplicated firewall to rate-limit impacted network interfaces. Check all the services listening to the ports with the following command:
$ sudo ss -l46ut
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
tcp LISTEN 0 128 [::]:ssh [::]:*
For each entry, verify that the ufw is configured to rate limit the service ports with the following command:
$ sudo ufw status
If any port with a state of "LISTEN" is not marked with the "LIMIT" action, run the following command, replacing "service" with the service that needs to be rate limited:
$ sudo ufw limit "service"
Rate-limiting can also be done on an interface. An example of adding a rate-limit on the eth0 interface follows:
$ sudo ufw limit in on eth0
Rationale:
This requirement addresses the configuration of the operating system to mitigate the impact of DoS attacks that have occurred or are ongoing on system availability. For each system, known and potential DoS attacks must be identified and solutions for each type implemented. A variety of technologies exist to limit or, in some cases, eliminate the effects of DoS attacks (e.g., limiting processes or establishing memory partitions). Employing increased capacity and bandwidth, combined with service redundancy, may reduce the susceptibility to some DoS attacks.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_ufw_rate_limit
References:
disaCCI-002385
os-srgSRG-OS-000420-GPOS-00186
stigidUBTU-20-010446
stigrefSV-238367r853444_rule
Group   Wireless Networking   Group contains 1 group and 1 rule
[ref]   Wireless networking, such as 802.11 (WiFi) and Bluetooth, can present a security risk to sensitive or classified systems and networks. Wireless networking hardware is much more likely to be included in laptop or portable systems than in desktops or servers.

Removal of hardware provides the greatest assurance that the wireless capability remains disabled. Acquisition policies often include provisions to prevent the purchase of equipment that will be used in sensitive spaces and includes wireless capabilities. If it is impractical to remove the wireless hardware, and policy permits the device to enter sensitive spaces as long as wireless is disabled, efforts should instead focus on disabling wireless capability via software.
Group   Disable Wireless Through Software Configuration   Group contains 1 rule
[ref]   If it is impossible to remove the wireless hardware from the device in question, disable as much of it as possible through software. The following methods can disable software support for wireless networking, but note that these methods do not prevent malicious software or careless users from re-activating the devices.

Rule   Deactivate Wireless Network Interfaces   [ref]

Deactivating wireless network interfaces should prevent normal usage of the wireless capability.

Verify that there are no wireless interfaces configured on the system with the following command:
$ ls -L -d /sys/class/net/*/wireless | xargs dirname | xargs basename -a
Rationale:
The use of wireless networking can introduce many different attack vectors into the organization's network. Common attack vectors such as malicious association and ad hoc networks will allow an attacker to spoof a wireless access point (AP), allowing validated systems to connect to the malicious AP and enabling the attacker to monitor and record network traffic. These malicious APs can also serve to create a man-in-the-middle attack or be used to create a denial of service to valid network resources.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_wireless_disable_interfaces
References:
cis-csc11, 12, 14, 15, 3, 8, 9
cobit5APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06
cui3.1.16
disaCCI-001443, CCI-001444, CCI-002421, CCI-002418
isa-62443-20094.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3
isa-62443-2013SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6
ism1315, 1319
iso27001-2013A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2
nistAC-18(a), AC-18(3), CM-7(a), CM-7(b), CM-6(a), MP-7
nist-csfPR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4
pcidssReq-1.3.3
os-srgSRG-OS-000299-GPOS-00117, SRG-OS-000300-GPOS-00118, SRG-OS-000424-GPOS-00188, SRG-OS-000481-GPOS-000481
stigidUBTU-20-010455
cis3.1.2
pcidss41.3.3, 1.3
stigrefSV-252704r942848_rule


if [ -n "$(find /sys/class/net/*/ -type d -name wireless)" ]; then
    interfaces=$(find /sys/class/net/*/wireless -type d -name wireless | xargs -0 dirname | xargs basename)

    for i in $interfaces; do
        ip link set dev "$i" down
        drivers=$(basename "$(readlink -f /sys/class/net/"$i"/device/driver)")
        echo "install $drivers /bin/false" >> /etc/modprobe.d/disable_wireless.conf
        modprobe -r "$drivers"
     done
fi

Complexity:low
Disruption:medium
Reboot:false
Strategy:unknown
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010455
  - NIST-800-171-3.1.16
  - NIST-800-53-AC-18(3)
  - NIST-800-53-AC-18(a)
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - NIST-800-53-MP-7
  - PCI-DSS-Req-1.3.3
  - PCI-DSSv4-1.3
  - PCI-DSSv4-1.3.3
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - unknown_strategy
  - wireless_disable_interfaces

- name: Service facts
  ansible.builtin.service_facts: null
  tags:
  - DISA-STIG-UBTU-20-010455
  - NIST-800-171-3.1.16
  - NIST-800-53-AC-18(3)
  - NIST-800-53-AC-18(a)
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - NIST-800-53-MP-7
  - PCI-DSS-Req-1.3.3
  - PCI-DSSv4-1.3
  - PCI-DSSv4-1.3.3
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - unknown_strategy
  - wireless_disable_interfaces

- name: Ensure NetworkManager is installed
  ansible.builtin.package:
    name: '{{ item }}'
    state: present
  with_items:
  - NetworkManager
  tags:
  - DISA-STIG-UBTU-20-010455
  - NIST-800-171-3.1.16
  - NIST-800-53-AC-18(3)
  - NIST-800-53-AC-18(a)
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - NIST-800-53-MP-7
  - PCI-DSS-Req-1.3.3
  - PCI-DSSv4-1.3
  - PCI-DSSv4-1.3.3
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - unknown_strategy
  - wireless_disable_interfaces

- name: NetworkManager Deactivate Wireless Network Interfaces
  command: nmcli radio wifi off
  when:
  - '''NetworkManager'' in ansible_facts.packages'
  - ansible_facts.services['NetworkManager.service'].state == 'running'
  tags:
  - DISA-STIG-UBTU-20-010455
  - NIST-800-171-3.1.16
  - NIST-800-53-AC-18(3)
  - NIST-800-53-AC-18(a)
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - NIST-800-53-MP-7
  - PCI-DSS-Req-1.3.3
  - PCI-DSSv4-1.3
  - PCI-DSSv4-1.3.3
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - unknown_strategy
  - wireless_disable_interfaces
Group   Transport Layer Security Support   Group contains 1 rule
[ref]   Support for Transport Layer Security (TLS), and its predecessor, the Secure Sockets Layer (SSL), is included in Red Hat Enterprise Linux in the OpenSSL software (RPM package openssl). TLS provides encrypted and authenticated network communications, and many network services include support for it. TLS or SSL can be leveraged to avoid any plaintext transmission of sensitive data.
For information on how to use OpenSSL, see http://www.openssl.org/docs/. Information on FIPS validation of OpenSSL is available at http://www.openssl.org/docs/fips.html and http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140val-all.htm.

Rule   Only Allow DoD PKI-established CAs   [ref]

The operating system must only allow the use of DoD PKI-established certificate authorities for verification of the establishment of protected sessions.
Rationale:
Untrusted Certificate Authorities (CA) can issue certificates, but they may be issued by organizations or individuals that seek to compromise DoD systems or by organizations with insufficient security controls. If the CA used for verifying the certificate is not a DoD-approved CA, trust of this CA has not been established. The DoD will only accept PKI-certificates obtained from a DoD-approved internal or external certificate authority. Reliance on CAs for the establishment of secure sessions includes, for example, the use of SSL/TLS certificates.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_only_allow_dod_certs
References:
disaCCI-002470
os-srgSRG-OS-000403-GPOS-00182
stigidUBTU-20-010443
stigrefSV-238364r880902_rule
Group   File Permissions and Masks   Group contains 7 groups and 29 rules
[ref]   Traditional Unix security relies heavily on file and directory permissions to prevent unauthorized users from reading or modifying files to which they should not have access.

Several of the commands in this section search filesystems for files or directories with certain characteristics, and are intended to be run on every local partition on a given system. When the variable PART appears in one of the commands below, it means that the command is intended to be run repeatedly, with the name of each local partition substituted for PART in turn.

The following command prints a list of all xfs partitions on the local system, which is the default filesystem for Ubuntu 20.04 installations:
$ mount -t xfs | awk '{print $3}'
For any systems that use a different local filesystem type, modify this command as appropriate.
Group   Verify Permissions on Important Files and Directories   Group contains 2 groups and 25 rules
[ref]   Permissions for many files on a system must be set restrictively to ensure sensitive information is properly protected. This section discusses important permission restrictions which can be verified to ensure that no harmful discrepancies have arisen.
Group   Verify Permissions on Files within /var/log Directory   Group contains 6 rules
[ref]   The /var/log directory contains files with logs of error messages in the system and should only be accessed by authorized personnel.

Rule   Verify Group Who Owns /var/log Directory   [ref]

To properly set the group owner of /var/log, run the command:
$ sudo chgrp syslog /var/log
Rationale:
The /var/log directory contains files with logs of error messages in the system and should only be accessed by authorized personnel.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_groupowner_var_log
References:
disaCCI-001314
os-srgSRG-OS-000206-GPOS-00084
app-srg-ctrSRG-APP-000118-CTR-000240
stigidUBTU-20-010417
stigrefSV-238338r654189_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
find -H /var/log/ -maxdepth 1 -type d -exec chgrp -L 110 {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Ensure group owner on /var/log/
  file:
    path: /var/log/
    state: directory
    group: '110'
  tags:
  - DISA-STIG-UBTU-20-010417
  - configure_strategy
  - file_groupowner_var_log
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify Group Who Owns /var/log/syslog File   [ref]

To properly set the group owner of /var/log/syslog, run the command:
$ sudo chgrp adm /var/log/syslog
Rationale:
The /var/log/syslog file contains logs of error messages in the system and should only be accessed by authorized personnel.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_groupowner_var_log_syslog
References:
disaCCI-001314
os-srgSRG-OS-000206-GPOS-00084
stigidUBTU-20-010420
stigrefSV-238341r654198_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
chgrp 4 /var/log/syslog

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Test for existence /var/log/syslog
  stat:
    path: /var/log/syslog
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010420
  - configure_strategy
  - file_groupowner_var_log_syslog
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner 4 on /var/log/syslog
  file:
    path: /var/log/syslog
    group: '4'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010420
  - configure_strategy
  - file_groupowner_var_log_syslog
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify User Who Owns /var/log Directory   [ref]

To properly set the owner of /var/log, run the command:
$ sudo chown root /var/log 
Rationale:
The /var/log directory contains files with logs of error messages in the system and should only be accessed by authorized personnel.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_owner_var_log
References:
disaCCI-001314
os-srgSRG-OS-000206-GPOS-00084
app-srg-ctrSRG-APP-000118-CTR-000240
stigidUBTU-20-010418
stigrefSV-238339r654192_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
find -H /var/log/ -maxdepth 1 -type d -exec chown -L 0 {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Ensure owner on directory /var/log/
  file:
    path: /var/log/
    state: directory
    owner: '0'
  tags:
  - DISA-STIG-UBTU-20-010418
  - configure_strategy
  - file_owner_var_log
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify User Who Owns /var/log/syslog File   [ref]

To properly set the owner of /var/log/syslog, run the command:
$ sudo chown syslog /var/log/syslog 
Rationale:
The /var/log/syslog file contains logs of error messages in the system and should only be accessed by authorized personnel.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_owner_var_log_syslog
References:
disaCCI-001314
os-srgSRG-OS-000206-GPOS-00084
stigidUBTU-20-010421
stigrefSV-238342r654201_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
chown 104 /var/log/syslog

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Test for existence /var/log/syslog
  stat:
    path: /var/log/syslog
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010421
  - configure_strategy
  - file_owner_var_log_syslog
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner 104 on /var/log/syslog
  file:
    path: /var/log/syslog
    owner: '104'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010421
  - configure_strategy
  - file_owner_var_log_syslog
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify Permissions on /var/log Directory   [ref]

To properly set the permissions of /var/log, run the command:
$ sudo chmod 0755 /var/log
Rationale:
The /var/log directory contains files with logs of error messages in the system and should only be accessed by authorized personnel.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_var_log
References:
disaCCI-001314
os-srgSRG-OS-000206-GPOS-00084
app-srg-ctrSRG-APP-000118-CTR-000240
stigidUBTU-20-010419
stigrefSV-238340r880879_rule


chmod 0755 /var/log/

if grep -q "^z \/var\/log " /usr/lib/tmpfiles.d/00rsyslog.conf; then
    sed -i --follow-symlinks "s/\(^z[[:space:]]\+\/var\/log[[:space:]]\+\)\(\([[:digit:]]\+\)[^ $]*\)/\10755/" /usr/lib/tmpfiles.d/00rsyslog.conf
fi

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Find /var/log/ file(s)
  command: 'find -H /var/log/ -maxdepth 1 -perm /u+s,g+ws,o+wt  -type d '
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010419
  - configure_strategy
  - file_permissions_var_log
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /var/log/ file(s)
  file:
    path: '{{ item }}'
    mode: u-s,g-ws,o-wt
    state: directory
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010419
  - configure_strategy
  - file_permissions_var_log
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify Permissions on /var/log/syslog File   [ref]

To properly set the permissions of /var/log/syslog, run the command:
$ sudo chmod 0640 /var/log/syslog
Rationale:
The /var/log/syslog file contains logs of error messages in the system and should only be accessed by authorized personnel.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_var_log_syslog
References:
disaCCI-001314
os-srgSRG-OS-000206-GPOS-00084
stigidUBTU-20-010422
stigrefSV-238343r654204_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure




chmod u-xs,g-xws,o-xwrt /var/log/syslog

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Test for existence /var/log/syslog
  stat:
    path: /var/log/syslog
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010422
  - configure_strategy
  - file_permissions_var_log_syslog
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure permission u-xs,g-xws,o-xwrt on /var/log/syslog
  file:
    path: /var/log/syslog
    mode: u-xs,g-xws,o-xwrt
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010422
  - configure_strategy
  - file_permissions_var_log_syslog
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
Group   Verify File Permissions Within Some Important Directories   Group contains 15 rules
[ref]   Some directories contain files whose confidentiality or integrity is notably important and may also be susceptible to misconfiguration over time, particularly if unpackaged software is installed. As such, an argument exists to verify that files' permissions within these directories remain configured correctly and restrictively.

Rule   Verify that Shared Library Directories Have Root Group Ownership   [ref]

System-wide shared library files, which are linked to executables during process load time or run time, are stored in the following directories by default:
/lib
/lib64
/usr/lib
/usr/lib64
Kernel modules, which can be added to the kernel during runtime, are also stored in /lib/modules. All files in these directories should be group-owned by the root user. If the directories, is found to be owned by a user other than root correct its ownership with the following command:
$ sudo chgrp root DIR
         
Rationale:
Files from shared library directories are loaded into the address space of processes (including privileged ones) or of the kernel itself at runtime. Proper ownership of library directories is necessary to protect the integrity of the system.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_dir_group_ownership_library_dirs
References:
disaCCI-001499
nistCM-5(6), CM-5(6).1
os-srgSRG-OS-000259-GPOS-00100
stigidUBTU-20-010431
stigrefSV-238352r654231_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
find -H /lib/  -type d -exec chgrp -L 0 {} \;
find -H /lib64/  -type d -exec chgrp -L 0 {} \;
find -H /usr/lib/  -type d -exec chgrp -L 0 {} \;
find -H /usr/lib64/  -type d -exec chgrp -L 0 {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Ensure group owner on /lib/ recursively
  file:
    path: /lib/
    state: directory
    recurse: true
    group: '0'
  tags:
  - DISA-STIG-UBTU-20-010431
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_group_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner on /lib64/ recursively
  file:
    path: /lib64/
    state: directory
    recurse: true
    group: '0'
  tags:
  - DISA-STIG-UBTU-20-010431
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_group_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner on /usr/lib/ recursively
  file:
    path: /usr/lib/
    state: directory
    recurse: true
    group: '0'
  tags:
  - DISA-STIG-UBTU-20-010431
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_group_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner on /usr/lib64/ recursively
  file:
    path: /usr/lib64/
    state: directory
    recurse: true
    group: '0'
  tags:
  - DISA-STIG-UBTU-20-010431
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_group_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify that system commands directories are group owned by root   [ref]

System commands files are stored in the following directories by default:
/bin
/sbin
/usr/bin
/usr/sbin
/usr/local/bin
/usr/local/sbin
All these directories should be owned by the root group. If the directory is found to be owned by a group other than root correct its ownership with the following command:
$ sudo chgrp root DIR
         
Rationale:
If the operating system allows any user to make changes to software libraries, then those changes might be implemented without undergoing the appropriate testing and approvals that are part of a robust change management process. This requirement applies to operating systems with software libraries that are accessible and configurable, as in the case of interpreted languages. Software libraries also include privileged programs which execute with escalated privileges. Only qualified and authorized individuals must be allowed to obtain access to information system components for purposes of initiating changes, including upgrades and modifications.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_dir_groupownership_binary_dirs
References:
disaCCI-001495
os-srgSRG-OS-000258-GPOS-00099
stigidUBTU-20-010425
stigrefSV-238346r654213_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
find -H /bin/  -type d -exec chgrp -L 0 {} \;
find -H /sbin/  -type d -exec chgrp -L 0 {} \;
find -H /usr/bin/  -type d -exec chgrp -L 0 {} \;
find -H /usr/sbin/  -type d -exec chgrp -L 0 {} \;
find -H /usr/local/bin/  -type d -exec chgrp -L 0 {} \;
find -H /usr/local/sbin/  -type d -exec chgrp -L 0 {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Ensure group owner on /bin/ recursively
  file:
    path: /bin/
    state: directory
    recurse: true
    group: '0'
  tags:
  - DISA-STIG-UBTU-20-010425
  - configure_strategy
  - dir_groupownership_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner on /sbin/ recursively
  file:
    path: /sbin/
    state: directory
    recurse: true
    group: '0'
  tags:
  - DISA-STIG-UBTU-20-010425
  - configure_strategy
  - dir_groupownership_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner on /usr/bin/ recursively
  file:
    path: /usr/bin/
    state: directory
    recurse: true
    group: '0'
  tags:
  - DISA-STIG-UBTU-20-010425
  - configure_strategy
  - dir_groupownership_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner on /usr/sbin/ recursively
  file:
    path: /usr/sbin/
    state: directory
    recurse: true
    group: '0'
  tags:
  - DISA-STIG-UBTU-20-010425
  - configure_strategy
  - dir_groupownership_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner on /usr/local/bin/ recursively
  file:
    path: /usr/local/bin/
    state: directory
    recurse: true
    group: '0'
  tags:
  - DISA-STIG-UBTU-20-010425
  - configure_strategy
  - dir_groupownership_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner on /usr/local/sbin/ recursively
  file:
    path: /usr/local/sbin/
    state: directory
    recurse: true
    group: '0'
  tags:
  - DISA-STIG-UBTU-20-010425
  - configure_strategy
  - dir_groupownership_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify that System Executable Have Root Ownership   [ref]

/bin
/sbin
/usr/bin
/usr/sbin
/usr/local/bin
/usr/local/sbin
All these directories should be owned by the root user. If any directory DIR in these directories is found to be owned by a user other than root, correct its ownership with the following command:
$ sudo chown root DIR
         
Rationale:
System binaries are executed by privileged users as well as system services, and restrictive permissions are necessary to ensure that their execution of these programs cannot be co-opted.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_dir_ownership_binary_dirs
References:
disaCCI-001495
os-srgSRG-OS-000258-GPOS-00099
stigidUBTU-20-010424
stigrefSV-238345r654210_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
find -H /bin/  -type d -exec chown -L 0 {} \;
find -H /sbin/  -type d -exec chown -L 0 {} \;
find -H /usr/bin/  -type d -exec chown -L 0 {} \;
find -H /usr/sbin/  -type d -exec chown -L 0 {} \;
find -H /usr/local/bin/  -type d -exec chown -L 0 {} \;
find -H /usr/local/sbin/  -type d -exec chown -L 0 {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Ensure owner on directory /bin/ recursively
  file:
    path: /bin/
    state: directory
    recurse: true
    owner: '0'
  tags:
  - DISA-STIG-UBTU-20-010424
  - configure_strategy
  - dir_ownership_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner on directory /sbin/ recursively
  file:
    path: /sbin/
    state: directory
    recurse: true
    owner: '0'
  tags:
  - DISA-STIG-UBTU-20-010424
  - configure_strategy
  - dir_ownership_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner on directory /usr/bin/ recursively
  file:
    path: /usr/bin/
    state: directory
    recurse: true
    owner: '0'
  tags:
  - DISA-STIG-UBTU-20-010424
  - configure_strategy
  - dir_ownership_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner on directory /usr/sbin/ recursively
  file:
    path: /usr/sbin/
    state: directory
    recurse: true
    owner: '0'
  tags:
  - DISA-STIG-UBTU-20-010424
  - configure_strategy
  - dir_ownership_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner on directory /usr/local/bin/ recursively
  file:
    path: /usr/local/bin/
    state: directory
    recurse: true
    owner: '0'
  tags:
  - DISA-STIG-UBTU-20-010424
  - configure_strategy
  - dir_ownership_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner on directory /usr/local/sbin/ recursively
  file:
    path: /usr/local/sbin/
    state: directory
    recurse: true
    owner: '0'
  tags:
  - DISA-STIG-UBTU-20-010424
  - configure_strategy
  - dir_ownership_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify that Shared Library Directories Have Root Ownership   [ref]

System-wide shared library files, which are linked to executables during process load time or run time, are stored in the following directories by default:
/lib
/lib64
/usr/lib
/usr/lib64
Kernel modules, which can be added to the kernel during runtime, are also stored in /lib/modules. All files in these directories should be owned by the root user. If the directories, is found to be owned by a user other than root correct its ownership with the following command:
$ sudo chown root DIR
         
Rationale:
Files from shared library directories are loaded into the address space of processes (including privileged ones) or of the kernel itself at runtime. Proper ownership of library directories is necessary to protect the integrity of the system.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_dir_ownership_library_dirs
References:
disaCCI-001499
nistCM-5(6), CM-5(6).1
os-srgSRG-OS-000259-GPOS-00100
stigidUBTU-20-010429
stigrefSV-238350r654225_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
find -H /lib/  -type d -exec chown -L 0 {} \;
find -H /lib64/  -type d -exec chown -L 0 {} \;
find -H /usr/lib/  -type d -exec chown -L 0 {} \;
find -H /usr/lib64/  -type d -exec chown -L 0 {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Ensure owner on directory /lib/ recursively
  file:
    path: /lib/
    state: directory
    recurse: true
    owner: '0'
  tags:
  - DISA-STIG-UBTU-20-010429
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner on directory /lib64/ recursively
  file:
    path: /lib64/
    state: directory
    recurse: true
    owner: '0'
  tags:
  - DISA-STIG-UBTU-20-010429
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner on directory /usr/lib/ recursively
  file:
    path: /usr/lib/
    state: directory
    recurse: true
    owner: '0'
  tags:
  - DISA-STIG-UBTU-20-010429
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner on directory /usr/lib64/ recursively
  file:
    path: /usr/lib64/
    state: directory
    recurse: true
    owner: '0'
  tags:
  - DISA-STIG-UBTU-20-010429
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify that System Executable Directories Have Restrictive Permissions   [ref]

System executables are stored in the following directories by default:
/bin
/sbin
/usr/bin
/usr/sbin
/usr/local/bin
/usr/local/sbin
These directories should not be group-writable or world-writable. If any directory DIR in these directories is found to be group-writable or world-writable, correct its permission with the following command:
$ sudo chmod go-w DIR
         
Rationale:
System binaries are executed by privileged users, as well as system services, and restrictive permissions are necessary to ensure execution of these programs cannot be co-opted.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_dir_permissions_binary_dirs
References:
disaCCI-001495
os-srgSRG-OS-000258-GPOS-00099
stigidUBTU-20-010423
stigrefSV-238344r654207_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure




find -H /bin/  -perm /u+s,g+ws,o+wt -type d -exec chmod u-s,g-ws,o-wt {} \;

find -H /sbin/  -perm /u+s,g+ws,o+wt -type d -exec chmod u-s,g-ws,o-wt {} \;

find -H /usr/bin/  -perm /u+s,g+ws,o+wt -type d -exec chmod u-s,g-ws,o-wt {} \;

find -H /usr/sbin/  -perm /u+s,g+ws,o+wt -type d -exec chmod u-s,g-ws,o-wt {} \;

find -H /usr/local/bin/  -perm /u+s,g+ws,o+wt -type d -exec chmod u-s,g-ws,o-wt {} \;

find -H /usr/local/sbin/  -perm /u+s,g+ws,o+wt -type d -exec chmod u-s,g-ws,o-wt {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Find /bin/ file(s) recursively
  command: 'find -H /bin/  -perm /u+s,g+ws,o+wt  -type d '
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010423
  - configure_strategy
  - dir_permissions_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /bin/ file(s)
  file:
    path: '{{ item }}'
    mode: u-s,g-ws,o-wt
    state: directory
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010423
  - configure_strategy
  - dir_permissions_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /sbin/ file(s) recursively
  command: 'find -H /sbin/  -perm /u+s,g+ws,o+wt  -type d '
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010423
  - configure_strategy
  - dir_permissions_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /sbin/ file(s)
  file:
    path: '{{ item }}'
    mode: u-s,g-ws,o-wt
    state: directory
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010423
  - configure_strategy
  - dir_permissions_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /usr/bin/ file(s) recursively
  command: 'find -H /usr/bin/  -perm /u+s,g+ws,o+wt  -type d '
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010423
  - configure_strategy
  - dir_permissions_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /usr/bin/ file(s)
  file:
    path: '{{ item }}'
    mode: u-s,g-ws,o-wt
    state: directory
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010423
  - configure_strategy
  - dir_permissions_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /usr/sbin/ file(s) recursively
  command: 'find -H /usr/sbin/  -perm /u+s,g+ws,o+wt  -type d '
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010423
  - configure_strategy
  - dir_permissions_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /usr/sbin/ file(s)
  file:
    path: '{{ item }}'
    mode: u-s,g-ws,o-wt
    state: directory
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010423
  - configure_strategy
  - dir_permissions_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /usr/local/bin/ file(s) recursively
  command: 'find -H /usr/local/bin/  -perm /u+s,g+ws,o+wt  -type d '
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010423
  - configure_strategy
  - dir_permissions_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /usr/local/bin/ file(s)
  file:
    path: '{{ item }}'
    mode: u-s,g-ws,o-wt
    state: directory
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010423
  - configure_strategy
  - dir_permissions_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /usr/local/sbin/ file(s) recursively
  command: 'find -H /usr/local/sbin/  -perm /u+s,g+ws,o+wt  -type d '
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010423
  - configure_strategy
  - dir_permissions_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /usr/local/sbin/ file(s)
  file:
    path: '{{ item }}'
    mode: u-s,g-ws,o-wt
    state: directory
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010423
  - configure_strategy
  - dir_permissions_binary_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify that Shared Library Directories Have Restrictive Permissions   [ref]

System-wide shared library directories, which contain are linked to executables during process load time or run time, are stored in the following directories by default:
/lib
/lib64
/usr/lib
/usr/lib64
Kernel modules, which can be added to the kernel during runtime, are stored in /lib/modules. All sub-directories in these directories should not be group-writable or world-writable. If any file in these directories is found to be group-writable or world-writable, correct its permission with the following command:
$ sudo chmod go-w DIR
         
Rationale:
If the operating system were to allow any user to make changes to software libraries, then those changes might be implemented without undergoing the appropriate testing and approvals that are part of a robust change management process. This requirement applies to operating systems with software libraries that are accessible and configurable, as in the case of interpreted languages. Software libraries also include privileged programs which execute with escalated privileges. Only qualified and authorized individuals must be allowed to obtain access to information system components for purposes of initiating changes, including upgrades and modifications.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_dir_permissions_library_dirs
References:
disaCCI-001499
nerc-cipCIP-003-8 R6
nistCM-5, CM-5(6), CM-5(6).1
os-srgSRG-OS-000259-GPOS-00100
stigidUBTU-20-010427
stigrefSV-238348r654219_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure




find -H /lib/  -perm /g+w,o+w -type d -exec chmod g-w,o-w {} \;

find -H /lib64/  -perm /g+w,o+w -type d -exec chmod g-w,o-w {} \;

find -H /usr/lib/  -perm /g+w,o+w -type d -exec chmod g-w,o-w {} \;

find -H /usr/lib64/  -perm /g+w,o+w -type d -exec chmod g-w,o-w {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Find /lib/ file(s) recursively
  command: 'find -H /lib/  -perm /g+w,o+w  -type d '
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010427
  - NIST-800-53-CM-5
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /lib/ file(s)
  file:
    path: '{{ item }}'
    mode: g-w,o-w
    state: directory
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010427
  - NIST-800-53-CM-5
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /lib64/ file(s) recursively
  command: 'find -H /lib64/  -perm /g+w,o+w  -type d '
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010427
  - NIST-800-53-CM-5
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /lib64/ file(s)
  file:
    path: '{{ item }}'
    mode: g-w,o-w
    state: directory
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010427
  - NIST-800-53-CM-5
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /usr/lib/ file(s) recursively
  command: 'find -H /usr/lib/  -perm /g+w,o+w  -type d '
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010427
  - NIST-800-53-CM-5
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /usr/lib/ file(s)
  file:
    path: '{{ item }}'
    mode: g-w,o-w
    state: directory
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010427
  - NIST-800-53-CM-5
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /usr/lib64/ file(s) recursively
  command: 'find -H /usr/lib64/  -perm /g+w,o+w  -type d '
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010427
  - NIST-800-53-CM-5
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /usr/lib64/ file(s)
  file:
    path: '{{ item }}'
    mode: g-w,o-w
    state: directory
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010427
  - NIST-800-53-CM-5
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - dir_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify that audit tools are owned by group root   [ref]

The Ubuntu 20.04 operating system audit tools must have the proper ownership configured to protected against unauthorized access. Verify it by running the following command:
$ stat -c "%n %G" /sbin/auditctl /sbin/aureport /sbin/ausearch /sbin/autrace /sbin/auditd /sbin/audispd /sbin/augenrules

/sbin/auditctl root
/sbin/aureport root
/sbin/ausearch root
/sbin/autrace root
/sbin/auditd root
/sbin/audispd root
/sbin/augenrules root
Audit tools needed to successfully view and manipulate audit information system activity and records. Audit tools include custom queries and report generators
Rationale:
Protecting audit information also includes identifying and protecting the tools used to view and manipulate log data. Therefore, protecting audit tools is necessary to prevent unauthorized operation on audit information. Operating systems providing tools to interface with audit information will leverage user permissions and roles identifying the user accessing the tools and the corresponding rights the user enjoys to make access decisions regarding the access to audit tools.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_groupownership_audit_binaries
References:
disaCCI-001493, CCI-001494
os-srgSRG-OS-000256-GPiOS-00097, SRG-OS-000257-GPOS-00098
stigidUBTU-20-010201
stigrefSV-238302r654081_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
chgrp 0 /sbin/auditctl
chgrp 0 /sbin/aureport
chgrp 0 /sbin/ausearch
chgrp 0 /sbin/autrace
chgrp 0 /sbin/auditd
chgrp 0 /sbin/audispd
chgrp 0 /sbin/augenrules

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Test for existence /sbin/auditctl
  stat:
    path: /sbin/auditctl
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner 0 on /sbin/auditctl
  file:
    path: /sbin/auditctl
    group: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/aureport
  stat:
    path: /sbin/aureport
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner 0 on /sbin/aureport
  file:
    path: /sbin/aureport
    group: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/ausearch
  stat:
    path: /sbin/ausearch
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner 0 on /sbin/ausearch
  file:
    path: /sbin/ausearch
    group: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/autrace
  stat:
    path: /sbin/autrace
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner 0 on /sbin/autrace
  file:
    path: /sbin/autrace
    group: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/auditd
  stat:
    path: /sbin/auditd
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner 0 on /sbin/auditd
  file:
    path: /sbin/auditd
    group: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/audispd
  stat:
    path: /sbin/audispd
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner 0 on /sbin/audispd
  file:
    path: /sbin/audispd
    group: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/augenrules
  stat:
    path: /sbin/augenrules
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure group owner 0 on /sbin/augenrules
  file:
    path: /sbin/augenrules
    group: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010201
  - configure_strategy
  - file_groupownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify that system commands files are group owned by root or a system account   [ref]

System commands files are stored in the following directories by default:
/bin
/sbin
/usr/bin
/usr/sbin
/usr/local/bin
/usr/local/sbin
All files in these directories should be owned by the root group, or a system account. If the directory, or any file in these directories, is found to be owned by a group other than root or a a system account correct its ownership with the following command:
$ sudo chgrp root FILE
         
Rationale:
If the operating system allows any user to make changes to software libraries, then those changes might be implemented without undergoing the appropriate testing and approvals that are part of a robust change management process. This requirement applies to operating systems with software libraries that are accessible and configurable, as in the case of interpreted languages. Software libraries also include privileged programs which execute with escalated privileges. Only qualified and authorized individuals must be allowed to obtain access to information system components for purposes of initiating changes, including upgrades and modifications.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_groupownership_system_commands_dirs
References:
disaCCI-001499
nistCM-5(6), CM-5(6).1
os-srgSRG-OS-000259-GPOS-00100
stigidUBTU-20-010458
anssiR50
stigrefSV-238378r832971_rule


for SYSCMDFILES in /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin
do
   find -L $SYSCMDFILES \! -group root -type f -exec chgrp root '{}' \;
done

Rule   Verify that audit tools are owned by root   [ref]

The Ubuntu 20.04 operating system audit tools must have the proper ownership configured to protected against unauthorized access. Verify it by running the following command:
$ stat -c "%n %U" /sbin/auditctl /sbin/aureport /sbin/ausearch /sbin/autrace /sbin/auditd /sbin/audispd /sbin/augenrules

/sbin/auditctl root
/sbin/aureport root
/sbin/ausearch root
/sbin/autrace root
/sbin/auditd root
/sbin/audispd root
/sbin/augenrules root
Audit tools needed to successfully view and manipulate audit information system activity and records. Audit tools include custom queries and report generators
Rationale:
Protecting audit information also includes identifying and protecting the tools used to view and manipulate log data. Therefore, protecting audit tools is necessary to prevent unauthorized operation on audit information. Operating systems providing tools to interface with audit information will leverage user permissions and roles identifying the user accessing the tools and the corresponding rights the user enjoys to make access decisions regarding the access to audit tools.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_ownership_audit_binaries
References:
disaCCI-001493, CCI-001494
os-srgSRG-OS-000256-GPiOS-00097, SRG-OS-000257-GPOS-00098
stigidUBTU-20-010200
stigrefSV-238301r654078_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
chown 0 /sbin/auditctl
chown 0 /sbin/aureport
chown 0 /sbin/ausearch
chown 0 /sbin/autrace
chown 0 /sbin/auditd
chown 0 /sbin/audispd
chown 0 /sbin/augenrules

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Test for existence /sbin/auditctl
  stat:
    path: /sbin/auditctl
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner 0 on /sbin/auditctl
  file:
    path: /sbin/auditctl
    owner: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/aureport
  stat:
    path: /sbin/aureport
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner 0 on /sbin/aureport
  file:
    path: /sbin/aureport
    owner: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/ausearch
  stat:
    path: /sbin/ausearch
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner 0 on /sbin/ausearch
  file:
    path: /sbin/ausearch
    owner: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/autrace
  stat:
    path: /sbin/autrace
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner 0 on /sbin/autrace
  file:
    path: /sbin/autrace
    owner: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/auditd
  stat:
    path: /sbin/auditd
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner 0 on /sbin/auditd
  file:
    path: /sbin/auditd
    owner: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/audispd
  stat:
    path: /sbin/audispd
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner 0 on /sbin/audispd
  file:
    path: /sbin/audispd
    owner: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/augenrules
  stat:
    path: /sbin/augenrules
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner 0 on /sbin/augenrules
  file:
    path: /sbin/augenrules
    owner: '0'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010200
  - configure_strategy
  - file_ownership_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify that System Executables Have Root Ownership   [ref]

System executables are stored in the following directories by default:
/bin
/sbin
/usr/bin
/usr/libexec
/usr/local/bin
/usr/local/sbin
/usr/sbin
All files in these directories should be owned by the root user. If any file FILE in these directories is found to be owned by a user other than root, correct its ownership with the following command:
$ sudo chown root FILE
         
Rationale:
System binaries are executed by privileged users as well as system services, and restrictive permissions are necessary to ensure that their execution of these programs cannot be co-opted.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_ownership_binary_dirs
References:
cis-csc12, 13, 14, 15, 16, 18, 3, 5
cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
disaCCI-001499
isa-62443-20094.3.3.7.3
isa-62443-2013SR 2.1, SR 5.2
iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
nistCM-5(6), CM-5(6).1, CM-6(a), AC-6(1)
nist-csfPR.AC-4, PR.DS-5
os-srgSRG-OS-000259-GPOS-00100
stigidUBTU-20-010457
anssiR50
stigrefSV-238377r832968_rule

Rule   Verify that Shared Library Files Have Root Ownership   [ref]

System-wide shared library files, which are linked to executables during process load time or run time, are stored in the following directories by default:
/lib
/lib64
/usr/lib
/usr/lib64
Kernel modules, which can be added to the kernel during runtime, are also stored in /lib/modules. All files in these directories should be owned by the root user. If the directory, or any file in these directories, is found to be owned by a user other than root correct its ownership with the following command:
$ sudo chown root FILE
         
Rationale:
Files from shared library directories are loaded into the address space of processes (including privileged ones) or of the kernel itself at runtime. Proper ownership is necessary to protect the integrity of the system.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_ownership_library_dirs
References:
cis-csc12, 13, 14, 15, 16, 18, 3, 5
cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
disaCCI-001499
isa-62443-20094.3.3.7.3
isa-62443-2013SR 2.1, SR 5.2
iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
nistCM-5(6), CM-5(6).1, CM-6(a), AC-6(1)
nist-csfPR.AC-4, PR.DS-5
os-srgSRG-OS-000259-GPOS-00100
stigidUBTU-20-010428
stigrefSV-238349r654222_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure

find  /lib/  -type f ! -uid 0 -regextype posix-extended -regex '^.*$' -exec chown -L 0 {} \;

find  /lib64/  -type f ! -uid 0 -regextype posix-extended -regex '^.*$' -exec chown -L 0 {} \;

find  /usr/lib/  -type f ! -uid 0 -regextype posix-extended -regex '^.*$' -exec chown -L 0 {} \;

find  /usr/lib64/  -type f ! -uid 0 -regextype posix-extended -regex '^.*$' -exec chown -L 0 {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Find /lib/ file(s) matching ^.*$ recursively
  command: find -H /lib/  -type f ! -uid 0 -regextype posix-extended -regex "^.*$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010428
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner on /lib/ file(s) matching ^.*$
  file:
    path: '{{ item }}'
    owner: '0'
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010428
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /lib64/ file(s) matching ^.*$ recursively
  command: find -H /lib64/  -type f ! -uid 0 -regextype posix-extended -regex "^.*$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010428
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner on /lib64/ file(s) matching ^.*$
  file:
    path: '{{ item }}'
    owner: '0'
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010428
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /usr/lib/ file(s) matching ^.*$ recursively
  command: find -H /usr/lib/  -type f ! -uid 0 -regextype posix-extended -regex "^.*$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010428
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner on /usr/lib/ file(s) matching ^.*$
  file:
    path: '{{ item }}'
    owner: '0'
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010428
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /usr/lib64/ file(s) matching ^.*$ recursively
  command: find -H /usr/lib64/  -type f ! -uid 0 -regextype posix-extended -regex
    "^.*$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010428
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure owner on /usr/lib64/ file(s) matching ^.*$
  file:
    path: '{{ item }}'
    owner: '0'
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010428
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_ownership_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify that audit tools Have Mode 0755 or less   [ref]

The Ubuntu 20.04 operating system audit tools must have the proper permissions configured to protected against unauthorized access. Verify it by running the following command:
$ stat -c "%n %a" /sbin/auditctl /sbin/aureport /sbin/ausearch /sbin/autrace /sbin/auditd /sbin/audispd /sbin/augenrules

/sbin/auditctl 755
/sbin/aureport 755
/sbin/ausearch 755
/sbin/autrace 755
/sbin/auditd 755
/sbin/audispd 755
/sbin/augenrules 755
Audit tools needed to successfully view and manipulate audit information system activity and records. Audit tools include custom queries and report generators
Rationale:
Protecting audit information also includes identifying and protecting the tools used to view and manipulate log data. Therefore, protecting audit tools is necessary to prevent unauthorized operation on audit information. Operating systems providing tools to interface with audit information will leverage user permissions and roles identifying the user accessing the tools and the corresponding rights the user enjoys to make access decisions regarding the access to audit tools.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_audit_binaries
References:
disaCCI-001493, CCI-001494
os-srgSRG-OS-000256-GPOS-00097, SRG-OS-000257-GPOS-00098
stigidUBTU-20-010199
stigrefSV-238300r654075_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure




chmod u-s,g-ws,o-wt /sbin/auditctl

chmod u-s,g-ws,o-wt /sbin/aureport

chmod u-s,g-ws,o-wt /sbin/ausearch

chmod u-s,g-ws,o-wt /sbin/autrace

chmod u-s,g-ws,o-wt /sbin/auditd

chmod u-s,g-ws,o-wt /sbin/audispd

chmod u-s,g-ws,o-wt /sbin/augenrules

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Test for existence /sbin/auditctl
  stat:
    path: /sbin/auditctl
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure permission u-s,g-ws,o-wt on /sbin/auditctl
  file:
    path: /sbin/auditctl
    mode: u-s,g-ws,o-wt
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/aureport
  stat:
    path: /sbin/aureport
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure permission u-s,g-ws,o-wt on /sbin/aureport
  file:
    path: /sbin/aureport
    mode: u-s,g-ws,o-wt
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/ausearch
  stat:
    path: /sbin/ausearch
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure permission u-s,g-ws,o-wt on /sbin/ausearch
  file:
    path: /sbin/ausearch
    mode: u-s,g-ws,o-wt
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/autrace
  stat:
    path: /sbin/autrace
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure permission u-s,g-ws,o-wt on /sbin/autrace
  file:
    path: /sbin/autrace
    mode: u-s,g-ws,o-wt
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/auditd
  stat:
    path: /sbin/auditd
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure permission u-s,g-ws,o-wt on /sbin/auditd
  file:
    path: /sbin/auditd
    mode: u-s,g-ws,o-wt
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/audispd
  stat:
    path: /sbin/audispd
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure permission u-s,g-ws,o-wt on /sbin/audispd
  file:
    path: /sbin/audispd
    mode: u-s,g-ws,o-wt
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Test for existence /sbin/augenrules
  stat:
    path: /sbin/augenrules
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure permission u-s,g-ws,o-wt on /sbin/augenrules
  file:
    path: /sbin/augenrules
    mode: u-s,g-ws,o-wt
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010199
  - configure_strategy
  - file_permissions_audit_binaries
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify that System Executables Have Restrictive Permissions   [ref]

System executables are stored in the following directories by default:
/bin
/sbin
/usr/bin
/usr/libexec
/usr/local/bin
/usr/local/sbin
/usr/sbin
All files in these directories should not be group-writable or world-writable. If any file FILE in these directories is found to be group-writable or world-writable, correct its permission with the following command:
$ sudo chmod go-w FILE
         
Rationale:
System binaries are executed by privileged users, as well as system services, and restrictive permissions are necessary to ensure execution of these programs cannot be co-opted.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_binary_dirs
References:
cis-csc12, 13, 14, 15, 16, 18, 3, 5
cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
disaCCI-001499
isa-62443-20094.3.3.7.3
isa-62443-2013SR 2.1, SR 5.2
iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
nistCM-5(6), CM-5(6).1, CM-6(a), AC-6(1)
nist-csfPR.AC-4, PR.DS-5
os-srgSRG-OS-000259-GPOS-00100
stigidUBTU-20-010456
anssiR50
stigrefSV-238376r654303_rule

DIRS="/bin /usr/bin /usr/local/bin /sbin /usr/sbin /usr/local/sbin /usr/libexec"
for dirPath in $DIRS; do
	find "$dirPath" -perm /022 -exec chmod go-w '{}' \;
done

Rule   Verify that Shared Library Files Have Restrictive Permissions   [ref]

System-wide shared library files, which are linked to executables during process load time or run time, are stored in the following directories by default:
/lib
/lib64
/usr/lib
/usr/lib64
Kernel modules, which can be added to the kernel during runtime, are stored in /lib/modules. All files in these directories should not be group-writable or world-writable. If any file in these directories is found to be group-writable or world-writable, correct its permission with the following command:
$ sudo chmod go-w FILE
         
Rationale:
Files from shared library directories are loaded into the address space of processes (including privileged ones) or of the kernel itself at runtime. Restrictive permissions are necessary to protect the integrity of the system.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_library_dirs
References:
cis-csc12, 13, 14, 15, 16, 18, 3, 5
cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
disaCCI-001499
isa-62443-20094.3.3.7.3
isa-62443-2013SR 2.1, SR 5.2
iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
nistCM-6(a), CM-5(6), CM-5(6).1, AC-6(1)
nist-csfPR.AC-4, PR.DS-5
os-srgSRG-OS-000259-GPOS-00100
stigidUBTU-20-010426
stigrefSV-238347r654216_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure




find  /lib/  -perm /g+w,o+w  -type f -regextype posix-extended -regex '^.*$' -exec chmod g-w,o-w {} \;

find  /lib64/  -perm /g+w,o+w  -type f -regextype posix-extended -regex '^.*$' -exec chmod g-w,o-w {} \;

find  /usr/lib/  -perm /g+w,o+w  -type f -regextype posix-extended -regex '^.*$' -exec chmod g-w,o-w {} \;

find  /usr/lib64/  -perm /g+w,o+w  -type f -regextype posix-extended -regex '^.*$' -exec chmod g-w,o-w {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Find /lib/ file(s) recursively
  command: find -H /lib/  -perm /g+w,o+w  -type f -regextype posix-extended -regex
    "^.*$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010426
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /lib/ file(s)
  file:
    path: '{{ item }}'
    mode: g-w,o-w
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010426
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /lib64/ file(s) recursively
  command: find -H /lib64/  -perm /g+w,o+w  -type f -regextype posix-extended -regex
    "^.*$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010426
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /lib64/ file(s)
  file:
    path: '{{ item }}'
    mode: g-w,o-w
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010426
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /usr/lib/ file(s) recursively
  command: find -H /usr/lib/  -perm /g+w,o+w  -type f -regextype posix-extended -regex
    "^.*$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010426
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /usr/lib/ file(s)
  file:
    path: '{{ item }}'
    mode: g-w,o-w
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010426
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Find /usr/lib64/ file(s) recursively
  command: find -H /usr/lib64/  -perm /g+w,o+w  -type f -regextype posix-extended
    -regex "^.*$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010426
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /usr/lib64/ file(s)
  file:
    path: '{{ item }}'
    mode: g-w,o-w
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010426
  - NIST-800-53-AC-6(1)
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - NIST-800-53-CM-6(a)
  - configure_strategy
  - file_permissions_library_dirs
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify the system-wide library files in directories "/lib", "/lib64", "/usr/lib/" and "/usr/lib64" are group-owned by root.   [ref]

System-wide library files are stored in the following directories by default:
/lib
/lib64
/usr/lib
/usr/lib64
All system-wide shared library files should be protected from unauthorised access. If any of these files is not group-owned by root, correct its group-owner with the following command:
$ sudo chgrp root FILE
         
Rationale:
If the operating system were to allow any user to make changes to software libraries, then those changes might be implemented without undergoing the appropriate testing and approvals that are part of a robust change management process. This requirement applies to operating systems with software libraries that are accessible and configurable, as in the case of interpreted languages. Software libraries also include privileged programs which execute with escalated privileges. Only qualified and authorized individuals must be allowed to obtain access to information system components for purposes of initiating changes, including upgrades and modifications.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_root_permissions_syslibrary_files
References:
disaCCI-001499
nistCM-5(6), CM-5(6).1
os-srgSRG-OS-000259-GPOS-00100
stigidUBTU-20-010430
stigrefSV-238351r832962_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure

find  /lib/  -type f ! -group 0 -regextype posix-extended -regex '^.*$' -exec chgrp -L 0 {} \;

find  /lib64/  -type f ! -group 0 -regextype posix-extended -regex '^.*$' -exec chgrp -L 0 {} \;

find  /usr/lib/  -type f ! -group 0 -regextype posix-extended -regex '^.*$' -exec chgrp -L 0 {} \;

find  /usr/lib64/  -type f ! -group 0 -regextype posix-extended -regex '^.*$' -exec chgrp -L 0 {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Find /lib/ file(s) matching ^.*$ recursively
  command: find -H /lib/  -type f ! -group 0 -regextype posix-extended -regex "^.*$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010430
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - root_permissions_syslibrary_files

- name: Ensure group owner on /lib/ file(s) matching ^.*$
  file:
    path: '{{ item }}'
    group: '0'
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010430
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - root_permissions_syslibrary_files

- name: Find /lib64/ file(s) matching ^.*$ recursively
  command: find -H /lib64/  -type f ! -group 0 -regextype posix-extended -regex "^.*$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010430
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - root_permissions_syslibrary_files

- name: Ensure group owner on /lib64/ file(s) matching ^.*$
  file:
    path: '{{ item }}'
    group: '0'
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010430
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - root_permissions_syslibrary_files

- name: Find /usr/lib/ file(s) matching ^.*$ recursively
  command: find -H /usr/lib/  -type f ! -group 0 -regextype posix-extended -regex
    "^.*$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010430
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - root_permissions_syslibrary_files

- name: Ensure group owner on /usr/lib/ file(s) matching ^.*$
  file:
    path: '{{ item }}'
    group: '0'
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010430
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - root_permissions_syslibrary_files

- name: Find /usr/lib64/ file(s) matching ^.*$ recursively
  command: find -H /usr/lib64/  -type f ! -group 0 -regextype posix-extended -regex
    "^.*$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010430
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - root_permissions_syslibrary_files

- name: Ensure group owner on /usr/lib64/ file(s) matching ^.*$
  file:
    path: '{{ item }}'
    group: '0'
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010430
  - NIST-800-53-CM-5(6)
  - NIST-800-53-CM-5(6).1
  - configure_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - root_permissions_syslibrary_files

Rule   Verify that All World-Writable Directories Have Sticky Bits Set   [ref]

When the so-called 'sticky bit' is set on a directory, only the owner of a given file may remove that file from the directory. Without the sticky bit, any user with write access to a directory may remove any file in the directory. Setting the sticky bit prevents users from removing each other's files. In cases where there is no reason for a directory to be world-writable, a better solution is to remove that permission rather than to set the sticky bit. However, if a directory is used by a particular application, consult that application's documentation instead of blindly changing modes.
To set the sticky bit on a world-writable directory DIR, run the following command:
$ sudo chmod +t DIR
        
Warning:  This rule can take a long time to perform the check and might consume a considerable amount of resources depending on the number of directories present on the system. It is not a problem in most cases, but especially systems with a large number of directories can be affected. See https://access.redhat.com/articles/6999111.
Rationale:
Failing to set the sticky bit on public directories allows unauthorized users to delete files in the directory structure.

The only authorized public directories are those temporary directories supplied with the system, or those designed to be temporary file repositories. The setting is normally reserved for directories used by the system, by users for temporary file storage (such as /tmp), and for directories requiring global read/write access.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_dir_perms_world_writable_sticky_bits
References:
cis-csc12, 13, 14, 15, 16, 18, 3, 5
cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
disaCCI-001090
isa-62443-20094.3.3.7.3
isa-62443-2013SR 2.1, SR 5.2
iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
nistCM-6(a), AC-6(1)
nist-csfPR.AC-4, PR.DS-5
os-srgSRG-OS-000138-GPOS-00069
stigidUBTU-20-010411
cis1.1.22
anssiR54
pcidss42.2.6, 2.2
stigrefSV-238332r654171_rule

df --local -P | awk '{if (NR!=1) print $6}' \
| xargs -I '$6' find '$6' -xdev -type d \
\( -perm -0002 -a ! -perm -1000 \) 2>/dev/null \
-exec chmod a+t {} +

Rule   Verify Permissions on /etc/audit/auditd.conf   [ref]

To properly set the permissions of /etc/audit/auditd.conf, run the command:
$ sudo chmod 0640 /etc/audit/auditd.conf
Rationale:
Without the capability to restrict the roles and individuals that can select which events are audited, unauthorized personnel may be able to prevent the auditing of critical events. Misconfigured audits may degrade the system's performance by overwhelming the audit log. Misconfigured audits may also make it more difficult to establish, correlate, and investigate the events relating to an incident or identify those responsible for one.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_etc_audit_auditd
References:
disaCCI-000171
nistAU-12(b)
os-srgSRG-OS-000063-GPOS-00032
stigidUBTU-20-010133
stigrefSV-238249r653922_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure




chmod u-xs,g-xws,o-xwrt /etc/audit/auditd.conf

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Test for existence /etc/audit/auditd.conf
  stat:
    path: /etc/audit/auditd.conf
  register: file_exists
  tags:
  - DISA-STIG-UBTU-20-010133
  - NIST-800-53-AU-12(b)
  - configure_strategy
  - file_permissions_etc_audit_auditd
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Ensure permission u-xs,g-xws,o-xwrt on /etc/audit/auditd.conf
  file:
    path: /etc/audit/auditd.conf
    mode: u-xs,g-xws,o-xwrt
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
  - DISA-STIG-UBTU-20-010133
  - NIST-800-53-AU-12(b)
  - configure_strategy
  - file_permissions_etc_audit_auditd
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify Permissions on /etc/audit/rules.d/*.rules   [ref]

To properly set the permissions of /etc/audit/rules.d/*.rules, run the command:
$ sudo chmod 0600 /etc/audit/rules.d/*.rules
Rationale:
Without the capability to restrict the roles and individuals that can select which events are audited, unauthorized personnel may be able to prevent the auditing of critical events. Misconfigured audits may degrade the system's performance by overwhelming the audit log. Misconfigured audits may also make it more difficult to establish, correlate, and investigate the events relating to an incident or identify those responsible for one.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_etc_audit_rulesd
References:
disaCCI-000171
nistAU-12(b)
os-srgSRG-OS-000063-GPOS-00032
stigidUBTU-20-010133
stigrefSV-238249r653922_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure




find -L /etc/audit/rules.d/ -maxdepth 1 -perm /u+xs,g+xwrs,o+xwrt  -type f -regextype posix-extended -regex '^.*rules$' -exec chmod u-xs,g-xwrs,o-xwrt {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Find /etc/audit/rules.d/ file(s)
  command: find -H /etc/audit/rules.d/ -maxdepth 1 -perm /u+xs,g+xwrs,o+xwrt  -type
    f -regextype posix-extended -regex "^.*rules$"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010133
  - NIST-800-53-AU-12(b)
  - configure_strategy
  - file_permissions_etc_audit_rulesd
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

- name: Set permissions for /etc/audit/rules.d/ file(s)
  file:
    path: '{{ item }}'
    mode: u-xs,g-xwrs,o-xwrt
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010133
  - NIST-800-53-AU-12(b)
  - configure_strategy
  - file_permissions_etc_audit_rulesd
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed

Rule   Verify permissions of log files   [ref]

Any operating system providing too much information in error messages risks compromising the data and security of the structure, and content of error messages needs to be carefully considered by the organization. Organizations carefully consider the structure/content of error messages. The extent to which information systems are able to identify and handle error conditions is guided by organizational policy and operational requirements. Information that could be exploited by adversaries includes, for example, erroneous logon attempts with passwords entered by mistake as the username, mission/business information that can be derived from (if not stated explicitly by) information recorded, and personal information, such as account numbers, social security numbers, and credit card numbers.
Rationale:
The Ubuntu 20.04 must generate error messages that provide information necessary for corrective actions without revealing information that could be exploited by adversaries.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_permissions_local_var_log
References:
disaCCI-001312
nistSI-11(a), SI-11(b), SI-11.1(iii)
nist-csfPR.AC-4, PR.DS-5
os-srgSRG-OS-000205-GPOS-00083
stigidUBTU-20-010416
cis4.2.3
pcidss410.3.1, 10.3
stigrefSV-238337r880876_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:configure




find  /var/log/  -perm /u+xs,g+xws,o+xwrt ! -name 'history.log' ! -name 'eipp.log.xz' ! -name '*[bw]tmp' ! -name '*lastlog' -type f -regextype posix-extended -regex '.*' -exec chmod u-xs,g-xws,o-xwrt {} \;

Complexity:low
Disruption:low
Reboot:false
Strategy:configure
- name: Find /var/log/ file(s) recursively
  command: find -H /var/log/  -perm /u+xs,g+xws,o+xwrt ! -name "history.log" ! -name
    "eipp.log.xz" ! -name "*[bw]tmp" ! -name "*lastlog" -type f -regextype posix-extended
    -regex ".*"
  register: files_found
  changed_when: false
  failed_when: false
  check_mode: false
  tags:
  - DISA-STIG-UBTU-20-010416
  - NIST-800-53-SI-11(a)
  - NIST-800-53-SI-11(b)
  - NIST-800-53-SI-11.1(iii)
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.1
  - configure_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - permissions_local_var_log

- name: Set permissions for /var/log/ file(s)
  file:
    path: '{{ item }}'
    mode: u-xs,g-xws,o-xwrt
    state: file
  with_items:
  - '{{ files_found.stdout_lines }}'
  tags:
  - DISA-STIG-UBTU-20-010416
  - NIST-800-53-SI-11(a)
  - NIST-800-53-SI-11(b)
  - NIST-800-53-SI-11.1(iii)
  - PCI-DSSv4-10.3
  - PCI-DSSv4-10.3.1
  - configure_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - permissions_local_var_log
Group   Restrict Dynamic Mounting and Unmounting of Filesystems   Group contains 1 rule
[ref]   Linux includes a number of facilities for the automated addition and removal of filesystems on a running system. These facilities may be necessary in many environments, but this capability also carries some risk -- whether direct risk from allowing users to introduce arbitrary filesystems, or risk that software flaws in the automated mount facility itself could allow an attacker to compromise the system.

This command can be used to list the types of filesystems that are available to the currently executing kernel:
$ find /lib/modules/`uname -r`/kernel/fs -type f -name '*.ko'
If these filesystems are not required then they can be explicitly disabled in a configuratio file in /etc/modprobe.d.

Rule   Disable Modprobe Loading of USB Storage Driver   [ref]

To prevent USB storage devices from being used, configure the kernel module loading system to prevent automatic loading of the USB storage driver. To configure the system to prevent the usb-storage kernel module from being loaded, add the following line to the file /etc/modprobe.d/usb-storage.conf:
install usb-storage /bin/false
This will prevent the modprobe program from loading the usb-storage module, but will not prevent an administrator (or another program) from using the insmod program to load the module manually.
Rationale:
USB storage devices such as thumb drives can be used to introduce malicious software.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_kernel_module_usb-storage_disabled
References:
cis-csc1, 12, 15, 16, 5
cobit5APO13.01, DSS01.04, DSS05.03, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
cui3.1.21
disaCCI-000778, CCI-001958, CCI-003959
hipaa164.308(a)(3)(i), 164.308(a)(3)(ii)(A), 164.310(d)(1), 164.310(d)(2), 164.312(a)(1), 164.312(a)(2)(iv), 164.312(b)
isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4
isa-62443-2013SR 1.1, SR 1.10, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.6
iso27001-2013A.11.2.6, A.13.1.1, A.13.2.1, A.18.1.4, A.6.2.1, A.6.2.2, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
nistCM-7(a), CM-7(b), CM-6(a), MP-7
nist-csfPR.AC-1, PR.AC-3, PR.AC-6, PR.AC-7
os-srgSRG-OS-000114-GPOS-00059, SRG-OS-000378-GPOS-00163, SRG-OS-000480-GPOS-00227
app-srg-ctrSRG-APP-000141-CTR-000315
stigidUBTU-20-010461
cis1.1.24
pcidss43.4.2, 3.4
stigrefSV-251505r942851_rule

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

if LC_ALL=C grep -q -m 1 "^install usb-storage" /etc/modprobe.d/usb-storage.conf ; then
	
	sed -i 's#^install usb-storage.*#install usb-storage /bin/false#g' /etc/modprobe.d/usb-storage.conf
else
	echo -e "\n# Disable per security requirements" >> /etc/modprobe.d/usb-storage.conf
	echo "install usb-storage /bin/false" >> /etc/modprobe.d/usb-storage.conf
fi

if ! LC_ALL=C grep -q -m 1 "^blacklist usb-storage$" /etc/modprobe.d/usb-storage.conf ; then
	echo "blacklist usb-storage" >> /etc/modprobe.d/usb-storage.conf
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010461
  - NIST-800-171-3.1.21
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - NIST-800-53-MP-7
  - PCI-DSSv4-3.4
  - PCI-DSSv4-3.4.2
  - disable_strategy
  - kernel_module_usb-storage_disabled
  - low_complexity
  - medium_disruption
  - medium_severity
  - reboot_required

- name: Ensure kernel module 'usb-storage' is disabled
  lineinfile:
    create: true
    dest: /etc/modprobe.d/usb-storage.conf
    regexp: install\s+usb-storage
    line: install usb-storage /bin/false
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010461
  - NIST-800-171-3.1.21
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - NIST-800-53-MP-7
  - PCI-DSSv4-3.4
  - PCI-DSSv4-3.4.2
  - disable_strategy
  - kernel_module_usb-storage_disabled
  - low_complexity
  - medium_disruption
  - medium_severity
  - reboot_required

- name: Ensure kernel module 'usb-storage' is blacklisted
  lineinfile:
    create: true
    dest: /etc/modprobe.d/usb-storage.conf
    regexp: ^blacklist usb-storage$
    line: blacklist usb-storage
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010461
  - NIST-800-171-3.1.21
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - NIST-800-53-MP-7
  - PCI-DSSv4-3.4
  - PCI-DSSv4-3.4.2
  - disable_strategy
  - kernel_module_usb-storage_disabled
  - low_complexity
  - medium_disruption
  - medium_severity
  - reboot_required
Group   Restrict Programs from Dangerous Execution Patterns   Group contains 2 groups and 3 rules
[ref]   The recommendations in this section are designed to ensure that the system's features to protect against potentially dangerous program execution are activated. These protections are applied at the system initialization or kernel level, and defend against certain types of badly-configured or compromised programs.
Group   Enable ExecShield   Group contains 1 rule
[ref]   ExecShield describes kernel features that provide protection against exploitation of memory corruption errors such as buffer overflows. These features include random placement of the stack and other memory regions, prevention of execution in memory that should only hold data, and special handling of text buffers. These protections are enabled by default on 32-bit systems and controlled through sysctl variables kernel.exec-shield and kernel.randomize_va_space. On the latest 64-bit systems, kernel.exec-shield cannot be enabled or disabled with sysctl.

Rule   Enable Randomized Layout of Virtual Address Space   [ref]

To set the runtime status of the kernel.randomize_va_space kernel parameter, run the following command:
$ sudo sysctl -w kernel.randomize_va_space=2
To make sure that the setting is persistent, add the following line to a file in the directory /etc/sysctl.d:
kernel.randomize_va_space = 2
Rationale:
Address space layout randomization (ASLR) makes it more difficult for an attacker to predict the location of attack code they have introduced into a process's address space during an attempt at exploitation. Additionally, ASLR makes it more difficult for an attacker to know the location of existing code in order to re-purpose it using return oriented programming (ROP) techniques.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_sysctl_kernel_randomize_va_space
References:
cui3.1.7
disaCCI-000366, CCI-002824
hipaa164.308(a)(1)(ii)(D), 164.308(a)(3), 164.308(a)(4), 164.310(b), 164.310(c), 164.312(a), 164.312(e)
nerc-cipCIP-002-5 R1.1, CIP-002-5 R1.2, CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 4.1, CIP-004-6 4.2, CIP-004-6 R2.2.3, CIP-004-6 R2.2.4, CIP-004-6 R2.3, CIP-004-6 R4, CIP-005-6 R1, CIP-005-6 R1.1, CIP-005-6 R1.2, CIP-007-3 R3, CIP-007-3 R3.1, CIP-007-3 R5.1, CIP-007-3 R5.1.2, CIP-007-3 R5.1.3, CIP-007-3 R5.2.1, CIP-007-3 R5.2.3, CIP-007-3 R8.4, CIP-009-6 R.1.1, CIP-009-6 R4
nistSC-30, SC-30(2), CM-6(a)
pcidssReq-2.2.1
os-srgSRG-OS-000433-GPOS-00193, SRG-OS-000480-GPOS-00227
app-srg-ctrSRG-APP-000450-CTR-001105
stigidUBTU-20-010448
cis1.6.2
anssiR9
pcidss43.3.1.1, 3.3.1, 3.3
stigrefSV-238369r853446_rule

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

# Comment out any occurrences of kernel.randomize_va_space from /etc/sysctl.d/*.conf files

for f in /etc/sysctl.d/*.conf /run/sysctl.d/*.conf /usr/local/lib/sysctl.d/*.conf; do


  # skip systemd-sysctl symlink (/etc/sysctl.d/99-sysctl.conf -> /etc/sysctl.conf)
  if [[ "$(readlink -f "$f")" == "/etc/sysctl.conf" ]]; then continue; fi

  matching_list=$(grep -P '^(?!#).*[\s]*kernel.randomize_va_space.*$' $f | uniq )
  if ! test -z "$matching_list"; then
    while IFS= read -r entry; do
      escaped_entry=$(sed -e 's|/|\\/|g' <<< "$entry")
      # comment out "kernel.randomize_va_space" matches to preserve user data
      sed -i --follow-symlinks "s/^${escaped_entry}$/# &/g" $f
    done <<< "$matching_list"
  fi
done

#
# Set sysctl config file which to save the desired value
#

SYSCONFIG_FILE="/etc/sysctl.conf"


#
# Set runtime for kernel.randomize_va_space
#
if [[ "$OSCAP_BOOTC_BUILD" != "YES" ]] ; then
    /sbin/sysctl -q -n -w kernel.randomize_va_space="2"
fi

#
# If kernel.randomize_va_space present in /etc/sysctl.conf, change value to "2"
#	else, add "kernel.randomize_va_space = 2" to /etc/sysctl.conf
#

# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^kernel.randomize_va_space")

# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "2"

# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^kernel.randomize_va_space\\>" "${SYSCONFIG_FILE}"; then
    escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
    LC_ALL=C sed -i --follow-symlinks "s/^kernel.randomize_va_space\\>.*/$escaped_formatted_output/gi" "${SYSCONFIG_FILE}"
else
    if [[ -s "${SYSCONFIG_FILE}" ]] && [[ -n "$(tail -c 1 -- "${SYSCONFIG_FILE}" || true)" ]]; then
        LC_ALL=C sed -i --follow-symlinks '$a'\\ "${SYSCONFIG_FILE}"
    fi
    printf '%s\n' "$formatted_output" >> "${SYSCONFIG_FILE}"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010448
  - NIST-800-171-3.1.7
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SC-30
  - NIST-800-53-SC-30(2)
  - PCI-DSS-Req-2.2.1
  - PCI-DSSv4-3.3
  - PCI-DSSv4-3.3.1
  - PCI-DSSv4-3.3.1.1
  - disable_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - reboot_required
  - sysctl_kernel_randomize_va_space

- name: List /etc/sysctl.d/*.conf files
  find:
    paths:
    - /etc/sysctl.d/
    - /run/sysctl.d/
    - /usr/local/lib/sysctl.d/
    contains: ^[\s]*kernel.randomize_va_space.*$
    patterns: '*.conf'
    file_type: any
  register: find_sysctl_d
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010448
  - NIST-800-171-3.1.7
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SC-30
  - NIST-800-53-SC-30(2)
  - PCI-DSS-Req-2.2.1
  - PCI-DSSv4-3.3
  - PCI-DSSv4-3.3.1
  - PCI-DSSv4-3.3.1.1
  - disable_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - reboot_required
  - sysctl_kernel_randomize_va_space

- name: Comment out any occurrences of kernel.randomize_va_space from config files
  replace:
    path: '{{ item.path }}'
    regexp: ^[\s]*kernel.randomize_va_space
    replace: '#kernel.randomize_va_space'
  loop: '{{ find_sysctl_d.files }}'
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010448
  - NIST-800-171-3.1.7
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SC-30
  - NIST-800-53-SC-30(2)
  - PCI-DSS-Req-2.2.1
  - PCI-DSSv4-3.3
  - PCI-DSSv4-3.3.1
  - PCI-DSSv4-3.3.1.1
  - disable_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - reboot_required
  - sysctl_kernel_randomize_va_space

- name: Ensure sysctl kernel.randomize_va_space is set to 2
  sysctl:
    name: kernel.randomize_va_space
    value: '2'
    sysctl_file: /etc/sysctl.conf
    state: present
    reload: true
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010448
  - NIST-800-171-3.1.7
  - NIST-800-53-CM-6(a)
  - NIST-800-53-SC-30
  - NIST-800-53-SC-30(2)
  - PCI-DSS-Req-2.2.1
  - PCI-DSSv4-3.3
  - PCI-DSSv4-3.3.1
  - PCI-DSSv4-3.3.1.1
  - disable_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - reboot_required
  - sysctl_kernel_randomize_va_space
Group   Enable Execute Disable (XD) or No Execute (NX) Support on x86 Systems   Group contains 1 rule
[ref]   Recent processors in the x86 family support the ability to prevent code execution on a per memory page basis. Generically and on AMD processors, this ability is called No Execute (NX), while on Intel processors it is called Execute Disable (XD). This ability can help prevent exploitation of buffer overflow vulnerabilities and should be activated whenever possible. Extra steps must be taken to ensure that this protection is enabled, particularly on 32-bit x86 systems. Other processors, such as Itanium and POWER, have included such support since inception and the standard kernel for those platforms supports the feature. This is enabled by default on the latest Oracle Linux, Red Hat and Fedora systems if supported by the hardware.

Rule   Enable NX or XD Support in the BIOS   [ref]

Reboot the system and enter the BIOS or Setup configuration menu. Navigate the BIOS configuration menu and make sure that the option is enabled. The setting may be located under a Security section. Look for Execute Disable (XD) on Intel-based systems and No Execute (NX) on AMD-based systems.
Rationale:
Computers with the ability to prevent this type of code execution frequently put an option in the BIOS that will allow users to turn the feature on or off at will.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_bios_enable_execution_restrictions
References:
cis-csc11, 3, 9
cobit5BAI10.01, BAI10.02, BAI10.03, BAI10.05
cui3.1.7
disaCCI-002824
isa-62443-20094.3.4.3.2, 4.3.4.3.3
isa-62443-2013SR 7.6
iso27001-2013A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4
nistSC-39, CM-6(a)
nist-csfPR.IP-1
os-srgSRG-OS-000433-GPOS-00192
app-srg-ctrSRG-APP-000450-CTR-001105
stigidUBTU-20-010447
pcidss42.2.1, 2.2
stigrefSV-238368r880910_rule

Rule   Restrict Access to Kernel Message Buffer   [ref]

To set the runtime status of the kernel.dmesg_restrict kernel parameter, run the following command:
$ sudo sysctl -w kernel.dmesg_restrict=1
To make sure that the setting is persistent, add the following line to a file in the directory /etc/sysctl.d:
kernel.dmesg_restrict = 1
Rationale:
Unprivileged access to the kernel syslog can expose sensitive kernel address information.
Severity: 
low
Rule ID:xccdf_org.ssgproject.content_rule_sysctl_kernel_dmesg_restrict
References:
cui3.1.5
disaCCI-001082, CCI-001090
hipaa164.308(a)(1)(ii)(D), 164.308(a)(3), 164.308(a)(4), 164.310(b), 164.310(c), 164.312(a), 164.312(e)
nistSI-11(a), SI-11(b)
osppFMT_SMF_EXT.1
os-srgSRG-OS-000132-GPOS-00067, SRG-OS-000138-GPOS-00069
app-srg-ctrSRG-APP-000243-CTR-000600
stigidUBTU-20-010401
anssiR9
stigrefSV-255913r880908_rule

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

# Comment out any occurrences of kernel.dmesg_restrict from /etc/sysctl.d/*.conf files

for f in /etc/sysctl.d/*.conf /run/sysctl.d/*.conf /usr/local/lib/sysctl.d/*.conf; do


  # skip systemd-sysctl symlink (/etc/sysctl.d/99-sysctl.conf -> /etc/sysctl.conf)
  if [[ "$(readlink -f "$f")" == "/etc/sysctl.conf" ]]; then continue; fi

  matching_list=$(grep -P '^(?!#).*[\s]*kernel.dmesg_restrict.*$' $f | uniq )
  if ! test -z "$matching_list"; then
    while IFS= read -r entry; do
      escaped_entry=$(sed -e 's|/|\\/|g' <<< "$entry")
      # comment out "kernel.dmesg_restrict" matches to preserve user data
      sed -i --follow-symlinks "s/^${escaped_entry}$/# &/g" $f
    done <<< "$matching_list"
  fi
done

#
# Set sysctl config file which to save the desired value
#

SYSCONFIG_FILE="/etc/sysctl.conf"


#
# Set runtime for kernel.dmesg_restrict
#
if [[ "$OSCAP_BOOTC_BUILD" != "YES" ]] ; then
    /sbin/sysctl -q -n -w kernel.dmesg_restrict="1"
fi

#
# If kernel.dmesg_restrict present in /etc/sysctl.conf, change value to "1"
#	else, add "kernel.dmesg_restrict = 1" to /etc/sysctl.conf
#

# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^kernel.dmesg_restrict")

# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "1"

# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^kernel.dmesg_restrict\\>" "${SYSCONFIG_FILE}"; then
    escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
    LC_ALL=C sed -i --follow-symlinks "s/^kernel.dmesg_restrict\\>.*/$escaped_formatted_output/gi" "${SYSCONFIG_FILE}"
else
    if [[ -s "${SYSCONFIG_FILE}" ]] && [[ -n "$(tail -c 1 -- "${SYSCONFIG_FILE}" || true)" ]]; then
        LC_ALL=C sed -i --follow-symlinks '$a'\\ "${SYSCONFIG_FILE}"
    fi
    printf '%s\n' "$formatted_output" >> "${SYSCONFIG_FILE}"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010401
  - NIST-800-171-3.1.5
  - NIST-800-53-SI-11(a)
  - NIST-800-53-SI-11(b)
  - disable_strategy
  - low_complexity
  - low_severity
  - medium_disruption
  - reboot_required
  - sysctl_kernel_dmesg_restrict

- name: List /etc/sysctl.d/*.conf files
  find:
    paths:
    - /etc/sysctl.d/
    - /run/sysctl.d/
    - /usr/local/lib/sysctl.d/
    contains: ^[\s]*kernel.dmesg_restrict.*$
    patterns: '*.conf'
    file_type: any
  register: find_sysctl_d
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010401
  - NIST-800-171-3.1.5
  - NIST-800-53-SI-11(a)
  - NIST-800-53-SI-11(b)
  - disable_strategy
  - low_complexity
  - low_severity
  - medium_disruption
  - reboot_required
  - sysctl_kernel_dmesg_restrict

- name: Comment out any occurrences of kernel.dmesg_restrict from config files
  replace:
    path: '{{ item.path }}'
    regexp: ^[\s]*kernel.dmesg_restrict
    replace: '#kernel.dmesg_restrict'
  loop: '{{ find_sysctl_d.files }}'
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010401
  - NIST-800-171-3.1.5
  - NIST-800-53-SI-11(a)
  - NIST-800-53-SI-11(b)
  - disable_strategy
  - low_complexity
  - low_severity
  - medium_disruption
  - reboot_required
  - sysctl_kernel_dmesg_restrict

- name: Ensure sysctl kernel.dmesg_restrict is set to 1
  sysctl:
    name: kernel.dmesg_restrict
    value: '1'
    sysctl_file: /etc/sysctl.conf
    state: present
    reload: true
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010401
  - NIST-800-171-3.1.5
  - NIST-800-53-SI-11(a)
  - NIST-800-53-SI-11(b)
  - disable_strategy
  - low_complexity
  - low_severity
  - medium_disruption
  - reboot_required
  - sysctl_kernel_dmesg_restrict
Group   Services   Group contains 9 groups and 22 rules
[ref]   The best protection against vulnerable software is running less software. This section describes how to review the software which Ubuntu 20.04 installs on a system and disable software which is not needed. It then enumerates the software packages installed on a default Ubuntu 20.04 system and provides guidance about which ones can be safely disabled.

Ubuntu 20.04 provides a convenient minimal install option that essentially installs the bare necessities for a functional system. When building Ubuntu 20.04 systems, it is highly recommended to select the minimal packages and then build up the system from there.
Group   APT service configuration   Group contains 1 rule
[ref]   The apt service manage the package management and update of the whole system. Its configuration need to be properly defined to ensure efficient security updates, packages and repository authentication and proper lifecycle management.

Rule   Disable unauthenticated repositories in APT configuration   [ref]

Unauthenticated repositories should not be used for updates.
Rationale:
Repositories hosts all packages that will be intsalled on the system during update. If a repository is not authenticated, the associated packages can't be trusted, and then should not be installed localy.
Severity: 
unknown
Rule ID:xccdf_org.ssgproject.content_rule_apt_conf_disallow_unauthenticated
References:
disaCCI-003992
os-srgSRG-OS-000366-GPOS-00153
stigidUBTU-20-010438
stigrefSV-238359r877463_rule
Group   Base Services   Group contains 1 rule
[ref]   This section addresses the base services that are installed on a Ubuntu 20.04 default installation which are not covered in other sections. Some of these services listen on the network and should be treated with particular discretion. Other services are local system utilities that may or may not be extraneous. In general, system services should be disabled if not required.

Rule   Disable KDump Kernel Crash Analyzer (kdump)   [ref]

The kdump-tools service provides a kernel crash dump analyzer. It uses the kexec system call to boot a secondary kernel ("capture" kernel) following a system crash, which can load information from the crashed kernel for analysis. The kdump-tools service can be disabled with the following command:
$ sudo systemctl mask --now kdump-tools.service
Rationale:
Kernel core dumps may contain the full contents of system memory at the time of the crash. Kernel core dumps consume a considerable amount of disk space and may result in denial of service by exhausting the available space on the target file system partition. Unless the system is used for kernel development or testing, there is little need to run the kdump service.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_service_kdump_disabled
References:
cis-csc11, 12, 14, 15, 3, 8, 9
cobit5APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06
disaCCI-000366
hipaa164.308(a)(1)(ii)(D), 164.308(a)(3), 164.308(a)(4), 164.310(b), 164.310(c), 164.312(a), 164.312(e)
isa-62443-20094.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3
isa-62443-2013SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6
iso27001-2013A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2
nistCM-7(a), CM-7(b), CM-6(a)
nist-csfPR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4
osppFMT_SMF_EXT.1.1
os-srgSRG-OS-000269-GPOS-00103, SRG-OS-000480-GPOS-00227
stigidUBTU-20-010413
stigrefSV-238334r654177_rule

Complexity:low
Disruption:low
Reboot:false
Strategy:disable
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then

SYSTEMCTL_EXEC='/usr/bin/systemctl'
"$SYSTEMCTL_EXEC" stop 'kdump-tools.service'
"$SYSTEMCTL_EXEC" disable 'kdump-tools.service'
"$SYSTEMCTL_EXEC" mask 'kdump-tools.service'
# Disable socket activation if we have a unit file for it
if "$SYSTEMCTL_EXEC" -q list-unit-files kdump-tools.socket; then
    "$SYSTEMCTL_EXEC" stop 'kdump-tools.socket'
    "$SYSTEMCTL_EXEC" mask 'kdump-tools.socket'
fi
# The service may not be running because it has been started and failed,
# so let's reset the state so OVAL checks pass.
# Service should be 'inactive', not 'failed' after reboot though.
"$SYSTEMCTL_EXEC" reset-failed 'kdump-tools.service' || true

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:medium
Reboot:true
Strategy:disable
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
spec:
  config:
    ignition:
      version: 3.1.0
    systemd:
      units:
      - name: kdump-tools.service
        enabled: false
        mask: true
      - name: kdump-tools.socket
        enabled: false
        mask: true


[customizations.services]
masked = ["kdump-tools"]

Complexity:low
Disruption:low
Reboot:false
Strategy:disable
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - DISA-STIG-UBTU-20-010413
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - disable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - service_kdump_disabled

- name: Disable KDump Kernel Crash Analyzer (kdump) - Collect systemd Services Present
    in the System
  ansible.builtin.command: systemctl -q list-unit-files --type service
  register: service_exists
  changed_when: false
  failed_when: service_exists.rc not in [0, 1]
  check_mode: false
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010413
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - disable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - service_kdump_disabled

- name: Disable KDump Kernel Crash Analyzer (kdump) - Ensure kdump-tools.service is
    Masked
  ansible.builtin.systemd:
    name: kdump-tools.service
    state: stopped
    enabled: false
    masked: true
  when:
  - '"linux-base" in ansible_facts.packages'
  - service_exists.stdout_lines is search("kdump-tools.service", multiline=True)
  tags:
  - DISA-STIG-UBTU-20-010413
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - disable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - service_kdump_disabled

- name: Unit Socket Exists - kdump-tools.socket
  ansible.builtin.command: systemctl -q list-unit-files kdump-tools.socket
  register: socket_file_exists
  changed_when: false
  failed_when: socket_file_exists.rc not in [0, 1]
  check_mode: false
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-20-010413
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - disable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - service_kdump_disabled

- name: Disable KDump Kernel Crash Analyzer (kdump) - Disable Socket kdump-tools
  ansible.builtin.systemd:
    name: kdump-tools.socket
    enabled: false
    state: stopped
    masked: true
  when:
  - '"linux-base" in ansible_facts.packages'
  - socket_file_exists.stdout_lines is search("kdump-tools.socket", multiline=True)
  tags:
  - DISA-STIG-UBTU-20-010413
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - disable_strategy
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - service_kdump_disabled

Complexity:low
Disruption:low
R