---
title: >-
  Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
  Words
description: Datadog, the leading service for cloud-scale monitoring.
breadcrumbs: >-
  Docs > Datadog Security > OOTB Rules > Ensure PAM Enforces Password
  Requirements - Prevent the Use of Dictionary Words
---

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

# Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary Words
 
## Description{% #description %}

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. pwquality checks dictionary words by default, so where `var_password_pam_pwquality_default_compliant` is true, the rule also passes when the pwquality configuration files leave `dictcheck` out.

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

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

var_password_pam_dictcheck='1'



if grep -sq dictcheck /etc/security/pwquality.conf.d/*.conf ; then
    sed -i "/dictcheck/d" /etc/security/pwquality.conf.d/*.conf
fi










# pwquality reads indented settings as well, and bash_replace_or_append
# replaces those that start a line, so remove the indented ones.
if [ -f "/etc/security/pwquality.conf" ]; then
    LC_ALL=C sed -i --follow-symlinks "/^[[:space:]]\+dictcheck\>/Id" "/etc/security/pwquality.conf"
fi
# 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
```

### 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:
  - DISA-STIG-UBTU-22-611030
  - 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 - Find pwquality.conf.d files
  ansible.builtin.find:
    paths: /etc/security/pwquality.conf.d/
    patterns: '*.conf'
  register: pwquality_conf_d_files
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpwquality1" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-22-611030
  - 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 dictcheck is not set in pwquality.conf.d
  ansible.builtin.lineinfile:
    path: '{{ item.path }}'
    regexp: ^\s*\bdictcheck\b.*
    state: absent
  with_items: '{{ pwquality_conf_d_files.files }}'
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpwquality1" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-22-611030
  - 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 libpam-pwquality is installed
  ansible.builtin.package:
    name: libpam-pwquality
    state: present
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpwquality1" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-22-611030
  - 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 - 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:
  - '"linux-base" in ansible_facts.packages'
  - '"libpwquality1" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-22-611030
  - 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
    ansible.builtin.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
    ansible.builtin.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
      mode: 420
    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
    environment:
      DEBIAN_FRONTEND: noninteractive
    changed_when: true
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpwquality1" in ansible_facts.packages'
  - result_pam_auth_update_present.stat.exists
  tags:
  - DISA-STIG-UBTU-22-611030
  - 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 - Remove indented settings of dictcheck
  ansible.builtin.lineinfile:
    path: /etc/security/pwquality.conf
    regexp: ^\s+dictcheck\b
    state: absent
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpwquality1" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-22-611030
  - 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 }}
    mode: 420
  when:
  - '"linux-base" in ansible_facts.packages'
  - '"libpwquality1" in ansible_facts.packages'
  tags:
  - DISA-STIG-UBTU-22-611030
  - 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
```
