Skip to content

Commit

Permalink
Merge pull request #835 from dev-sec/ssh_locked
Browse files Browse the repository at this point in the history
Modify PAM to allow SSH key based logins with locked passwords
  • Loading branch information
schurzi authored Dec 23, 2024
2 parents ab93a75 + b7f0bdd commit c53e8bc
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 1 deletion.
1 change: 1 addition & 0 deletions molecule/os_hardening/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- verify_tasks/pw_ageing.yml
- verify_tasks/netrc.yml
- verify_tasks/ignore_home_folders.yml
- verify_tasks/ssh_auth_locked.yml

# temp. disabled - https://github.com/dev-sec/ansible-collection-hardening/issues/690
# - name: Include PAM tests
Expand Down
90 changes: 90 additions & 0 deletions molecule/os_hardening/verify_tasks/ssh_auth_locked.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
- name: Install tools
package:
name: "{{ item }}"
state: present
ignore_errors: true
loop:
- sshpass
- openssh
- openssh-clients
- openssh-server

- name: Allow password Login for sshd
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
search_string: PasswordAuthentication no
line: PasswordAuthentication yes
when:
- ansible_facts.distribution == "Amazon"

- name: Start sshd service
ansible.builtin.service:
name: "{{ item }}"
state: started
ignore_errors: true
loop:
- sshd
- ssh

- name: Set password for test
ansible.builtin.set_fact:
test_pw: myTest!pw

- name: Create locked_user
user:
name: locked_user
password: "{{ test_pw | password_hash('sha512') }}"

- name: Create ssh-client-keypair
community.crypto.openssh_keypair:
path: /root/locked_user_id
type: ed25519
state: present
register: generated_key

- name: Add ssh-public-key to locked_user
ansible.posix.authorized_key:
user: locked_user
key: "{{ generated_key.public_key }}"
state: present

- name: Check successful login with password
ansible.builtin.shell:
cmd: sshpass -p {{ test_pw }} ssh -o StrictHostKeyChecking=no locked_user@localhost echo "success"

- name: Check successful login with ssh key
ansible.builtin.shell:
cmd: ssh -i /root/locked_user_id -o StrictHostKeyChecking=no locked_user@localhost echo "success"

- name: Set password change date for locked_user
ansible.builtin.shell:
cmd: chage -d 2020-01-01 locked_user

- name: Check unsuccessful login with password
ansible.builtin.shell:
cmd: sshpass -p {{ test_pw }} ssh -o StrictHostKeyChecking=no locked_user@localhost echo "success"
register: output
ignore_errors: true

- name: Assert check unsuccessful login
ansible.builtin.assert:
that:
- output.rc | int == 1
- "'WARNING: Your password has expired.' in output.stderr"
- "'success' not in output.stdout"
when:
- ansible_facts.os_family != "Suse"

- name: Assert check unsuccessful login
ansible.builtin.assert:
that:
- output.rc | int == 5
- output.stderr | length == 0
- output.stdout | length == 0
when:
- ansible_facts.os_family == "Suse"

- name: Check successful login with ssh key
ansible.builtin.shell:
cmd: ssh -i /root/locked_user_id -o StrictHostKeyChecking=no locked_user@localhost echo "success"
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ ansible-core==2.18.1
docker==7.1.0
jmespath==1.0.1
aar-doc==2.0.1
passlib==1.7.4
12 changes: 12 additions & 0 deletions roles/os_hardening/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ We are setting this sysctl to a default of `32`, some systems only support small
vm.mmap_rnd_bits: 16
```

### password expiry and SSH key based logins

With default PAM configuration setting a password expiry for users will also block SSH key logins after the password has expired.
We have added a flag for PAM to ignore the expiry if SSH keys or other login mechanisms are used.
If you choose to use your own PAM configuration please adjust it accordingly to contain `no_pass_expiry` in the `account` stage for the `pam_unix.so` module.

A valid example would look like this:

```text
account required pam_unix.so no_pass_expiry
```

## Testing with inspec

If you're using inspec to test your machines after applying this role, please make sure to add the connecting user to the `os_ignore_users`-variable.
Expand Down
18 changes: 18 additions & 0 deletions roles/os_hardening/tasks/pam.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,24 @@
when:
- ansible_facts.os_family == 'RedHat'

- name: Allow Login with SSH Keys, when user password is expired
ansible.builtin.lineinfile:
path: /etc/pam.d/system-auth
backrefs: true
regexp: "^(account.*pam_unix.so(?!.*no_pass_expiry).*)$"
line: '\1 no_pass_expiry'
when:
- ansible_facts.os_family == 'Archlinux'

- name: Allow Login with SSH Keys, when user password is expired
ansible.builtin.lineinfile:
path: /etc/pam.d/common-account
backrefs: true
regexp: "^(account.*pam_unix.so(?!.*no_pass_expiry).*)$"
line: '\1 no_pass_expiry'
when:
- ansible_facts.os_family == 'Suse'

- name: NSA 2.3.3.5 Upgrade Password Hashing Algorithm to SHA-512
ansible.builtin.template:
src: etc/libuser.conf.j2
Expand Down
7 changes: 7 additions & 0 deletions roles/os_hardening/tasks/pam_debian.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,10 @@
state: absent
when:
- not os_auth_pam_passwdqc_enable

- name: Allow Login with SSH Keys, when user password is expired
ansible.builtin.lineinfile:
path: /etc/pam.d/common-account
backrefs: true
regexp: "^(account.*pam_unix.so(?!.*no_pass_expiry).*)$"
line: '\1 no_pass_expiry'
2 changes: 1 addition & 1 deletion roles/os_hardening/templates/etc/pam.d/rhel_auth.j2
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ auth required pam_deny.so
{% if os_auth_retries|int > 0 %}
account required pam_faillock.so
{% endif %}
account required pam_unix.so
account required pam_unix.so no_pass_expiry
account sufficient pam_localuser.so
account sufficient pam_succeed_if.so uid < 1000 quiet
{% if (os_auth_pam_sssd_enable | bool) %}
Expand Down

0 comments on commit c53e8bc

Please sign in to comment.