---
title: Set PAM Password Hashing Algorithm - system-auth
description: Datadog, the leading service for cloud-scale monitoring.
breadcrumbs: >-
  Docs > Datadog Security > OOTB Rules > Set PAM Password Hashing Algorithm -
  system-auth
---

> For the complete documentation index, see [llms.txt](https://docs.datadoghq.com/llms.txt).

# Set PAM Password Hashing Algorithm - system-auth
 
## Description{% #description %}

The PAM system service can be configured to only store encrypted representations of passwords. In "/etc/pam.d/common-password", the `password` section of the file controls which PAM modules to execute during a password change. Set the `pam_unix.so` module in the `password` section to include one hashing algorithm of `yescrypt`, which lists one algorithm, or several separated by a vertical bar, and no other hashing algorithm. The remediation writes the first algorithm it lists. The line looks as shown below:

```
password    [success=1 default=ignore]   pam_unix.so algorithm
          other arguments...
```

This will help ensure that new passwords for local users will be stored using that algorithm.

## Rationale{% #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.

This setting ensures user and group account administration utilities are configured to store only encrypted representations of passwords. Additionally, the `crypt_style` configuration option in `/etc/libuser.conf` ensures the use of a strong hashing algorithm that makes password cracking attacks more difficult.

## Remediation{% #remediation %}

### Shell script{% #shell-script %}

The following script can be run on the host to remediate the issue.

```bash
#!/bin/bash

# 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}' 'libpam-runtime' 2>/dev/null | grep -q '^installed$'; }; then

var_password_hashing_algorithm_pam='yescrypt'


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

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"
            chmod 0644 "$conf_path"/"$conf_name"
            sed -i 's/^Name: .*/Name: Unix authentication (ComplianceAsCode)/' "$conf_path"/"$conf_name"
            sed -i 's/Priority: [0-9]\+/Priority: 257\
Conflicts: unix/' "$conf_path"/"$conf_name"
            DEBIAN_FRONTEND=noninteractive pam-auth-update --enable "$conf_name" --disable unix
        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
PAM_FILE_PATH=/usr/share/pam-configs/cac_unix

# Ensure all the hashing algorithm option is removed.
declare -a HASHING_ALGORITHMS_OPTIONS=("sha512" "yescrypt" "gost_yescrypt" "blowfish" "sha256" "md5" "bigcrypt")

for hash_option in "${HASHING_ALGORITHMS_OPTIONS[@]}"; do
  sed -i -E '/^Password:/,/^[^[:space:]]/ {
    /pam_unix\.so/ {
      s/\s*\b'"$hash_option"'\b//g
    }
    }' "$PAM_FILE_PATH"
    sed -i -E '/^Password-Initial:/,/^[^[:space:]]/ {
    /pam_unix\.so/ {
      s/\s*\b'"$hash_option"'\b//g
    }
    }' "$PAM_FILE_PATH"
    DEBIAN_FRONTEND=noninteractive pam-auth-update
done

if ! grep -qzP "Password:\s*\n\s+.*\s+pam_unix.so\s+.*\b$var_password_hashing_algorithm_pam\b" "$PAM_FILE_PATH"; then
  sed -i -E '/^Password:/,/^[^[:space:]]/ {
    /pam_unix\.so/ {
        s/$/ '"$var_password_hashing_algorithm_pam"'/g
    }
}' "$PAM_FILE_PATH"
fi

if ! grep -qzP "Password-Initial:\s*\n\s+.*\s+pam_unix.so\s+.*\b$var_password_hashing_algorithm_pam\b" "$PAM_FILE_PATH"; then
  sed -i -E '/^Password-Initial:/,/^[^[:space:]]/ {
    /pam_unix\.so/ {
        s/$/ '"$var_password_hashing_algorithm_pam"'/g
    }
}' "$PAM_FILE_PATH"
fi

DEBIAN_FRONTEND=noninteractive pam-auth-update

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

### Ansible playbook{% #ansible-playbook %}

The following playbook can be run with Ansible to remediate the issue.

```gdscript3
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.6.2.2
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(c)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.1
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.2
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - set_password_hashing_algorithm_systemauth
- name: XCCDF Value var_password_hashing_algorithm_pam # promote to variable
  set_fact:
    var_password_hashing_algorithm_pam: !!str yescrypt
  tags:
    - always

- name: Set PAM Password Hashing Algorithm - system-auth - Check if /usr/share/pam-configs/cac_unix
    is present
  ansible.builtin.stat:
    path: /usr/share/pam-configs/cac_unix
  register: result_pam_cac_unix_before
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpam-runtime" in ansible_facts.packages'
  tags:
  - CJIS-5.6.2.2
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(c)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.1
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.2
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - set_password_hashing_algorithm_systemauth

- name: Set PAM Password Hashing Algorithm - system-auth - Check the unix profile
    of libpam-runtime
  ansible.builtin.stat:
    path: /usr/share/pam-configs/unix
    checksum_algorithm: md5
  register: result_pam_unix_profile
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpam-runtime" in ansible_facts.packages'
  - not result_pam_cac_unix_before.stat.exists
  tags:
  - CJIS-5.6.2.2
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(c)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.1
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.2
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - set_password_hashing_algorithm_systemauth

- name: Set PAM Password Hashing Algorithm - system-auth - Read the checksums of libpam-runtime
  ansible.builtin.slurp:
    src: /var/lib/dpkg/info/libpam-runtime.md5sums
  register: result_libpam_runtime_md5sums
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpam-runtime" in ansible_facts.packages'
  - not result_pam_cac_unix_before.stat.exists
  - result_pam_unix_profile.stat.exists
  tags:
  - CJIS-5.6.2.2
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(c)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.1
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.2
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - set_password_hashing_algorithm_systemauth

- name: Set PAM Password Hashing Algorithm - system-auth - Create /usr/share/pam-configs/cac_unix
    from the unix profile
  block:

  - name: Set PAM Password Hashing Algorithm - system-auth - Copy the unix profile
      to cac_unix
    ansible.builtin.copy:
      src: /usr/share/pam-configs/unix
      dest: /usr/share/pam-configs/cac_unix
      remote_src: true
      mode: '0644'

  - name: Set PAM Password Hashing Algorithm - system-auth - Name the cac_unix profile
    ansible.builtin.lineinfile:
      path: /usr/share/pam-configs/cac_unix
      regexp: '^Name: '
      line: 'Name: Unix authentication (ComplianceAsCode)'

  - name: Set PAM Password Hashing Algorithm - system-auth - Give the cac_unix profile
      precedence over unix
    ansible.builtin.replace:
      path: /usr/share/pam-configs/cac_unix
      regexp: '^Priority: [0-9]+$'
      replace: |-
        Priority: 257
        Conflicts: unix

  - name: Set PAM Password Hashing Algorithm - system-auth - Enable the cac_unix profile
      in place of unix
    ansible.builtin.command:
      cmd: pam-auth-update --enable cac_unix --disable unix
    environment:
      DEBIAN_FRONTEND: noninteractive
    changed_when: true
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpam-runtime" in ansible_facts.packages'
  - not result_pam_cac_unix_before.stat.exists
  - result_pam_unix_profile.stat.exists
  - result_pam_unix_profile.stat.checksum in (result_libpam_runtime_md5sums.content
    | b64decode)
  tags:
  - CJIS-5.6.2.2
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(c)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.1
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.2
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - set_password_hashing_algorithm_systemauth

- name: Set PAM Password Hashing Algorithm - system-auth - Check if /usr/share/pam-configs/cac_unix
    is present
  ansible.builtin.stat:
    path: /usr/share/pam-configs/cac_unix
  register: result_pam_cac_unix_present
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpam-runtime" in ansible_facts.packages'
  tags:
  - CJIS-5.6.2.2
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(c)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.1
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.2
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - set_password_hashing_algorithm_systemauth

- name: Set PAM Password Hashing Algorithm - system-auth - Use only the correct hashing
    algorithm in /usr/share/pam-configs/cac_unix
  block:

  - name: Set PAM Password Hashing Algorithm - system-auth - Remove the other hashing
      algorithm options of pam_unix.so
    ansible.builtin.replace:
      path: /usr/share/pam-configs/cac_unix
      regexp: ^(Password(?:-Initial)?:\s*[^\n]*pam_unix\.so[^\n]*?)\s+{{ item }}\b
      replace: \1
    when: item != var_password_hashing_algorithm_pam.split('|')[0]
    loop:
    - sha512
    - yescrypt
    - gost_yescrypt
    - blowfish
    - sha256
    - md5
    - bigcrypt
    register: result_pam_cac_unix_options_removal

  - name: Set PAM Password Hashing Algorithm - system-auth - Add the hashing algorithm
      option to pam_unix.so
    ansible.builtin.replace:
      path: /usr/share/pam-configs/cac_unix
      regexp: ^(Password(?:-Initial)?:\s*(?![^\n]*\b{{ var_password_hashing_algorithm_pam.split("|")[0]
        }}\b)[^\n]*pam_unix\.so[^\n]*)$
      replace: \1 {{ var_password_hashing_algorithm_pam.split("|")[0] }}
    register: result_pam_cac_unix_option_addition

  - name: Set PAM Password Hashing Algorithm - system-auth - Ensure pam-auth-update
      profile changes are applied
    ansible.builtin.command:
      cmd: pam-auth-update
    environment:
      DEBIAN_FRONTEND: noninteractive
    changed_when: true
    when: result_pam_cac_unix_options_removal is changed or result_pam_cac_unix_option_addition
      is changed
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpam-runtime" in ansible_facts.packages'
  - result_pam_cac_unix_present.stat.exists
  tags:
  - CJIS-5.6.2.2
  - NIST-800-53-CM-6(a)
  - NIST-800-53-IA-5(1)(c)
  - NIST-800-53-IA-5(c)
  - PCI-DSS-Req-8.2.1
  - PCI-DSSv4-8.3
  - PCI-DSSv4-8.3.2
  - configure_strategy
  - low_complexity
  - medium_disruption
  - medium_severity
  - no_reboot_needed
  - set_password_hashing_algorithm_systemauth
```

## Warning{% #warning %}

The hashing algorithms to be used with pam_unix.so are defined with independent module options. There are at least 7 possible algorithms and likely more algorithms will be introduced along the time. Due the the number of options and its possible combinations, the use of multiple hashing algorithm options may bring unexpected behaviors to the system. For this reason the check will pass only when one hashing algorithm option is defined and is aligned to the "var_password_hashing_algorithm_pam" variable. The remediation will ensure the correct option and remove any other extra hashing algorithm option.
