Skip to content

Commit

Permalink
Merge branch 'rbash'
Browse files Browse the repository at this point in the history
* Fixes #31
* Thanks to the 🛡️-crew for playing ;)
  • Loading branch information
pyllyukko committed Feb 22, 2025
2 parents 21d1d07 + 0a2e166 commit bc44a3e
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 10 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/ansible-playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,11 @@ jobs:
- name: Archive Lynis log
uses: actions/upload-artifact@v4
with:
name: lynis-shells.log
path: /var/log/lynis.log
name: shells
path: |
/var/log/lynis.log
/etc/shells
/etc/profile
- name: Check Lynis score
run: sudo bash tests/check_lynis_score.sh 100
malware:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/shellcheck.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
name: shellcheck
on: [push, pull_request]
env:
ANSIBLE_FORCE_COLOR: '1'
jobs:
profile_d:
runs-on: ubuntu-latest
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ For a complete list you can run `ansible-playbook --list-tasks harden.yml`.
* [![ca-certs](https://github.com/pyllyukko/harden.yml/actions/workflows/ca-certs.yml/badge.svg)](https://github.com/pyllyukko/harden.yml/actions/workflows/ca-certs.yml)
* You can also run `make /etc/ssl/certs/ca-certificates.crt` to update the CAs
* :shell: Restricts the number of available shells (`/etc/shells`)
* :shell: Creates an option to use a [restricted shell](https://en.wikipedia.org/wiki/Restricted_shell) ([rbash](https://www.gnu.org/software/bash/manual/html_node/The-Restricted-Shell.html))
* Only available for Debian & Slackware and for the `sshd` service because of the required PAM configuration changes (regarding `pam_env` & enforcing `PATH`)
* :information_source: See [Restricted shell](https://github.com/pyllyukko/harden.yml/wiki/Restricted-shell)
* :warning: **WARNING**: Contains plenty of caveats, details and hazards. Make sure you read and understand (at least) everything in the aforementioned [wiki page](https://github.com/pyllyukko/harden.yml/wiki/Restricted-shell), test it thoroughly and accept the risk that it may contain escapes.

### Slackware specific

Expand Down
2 changes: 2 additions & 0 deletions ansible.cfg
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
[privilege_escalation]
become_exe = /usr/bin/sudo
13 changes: 11 additions & 2 deletions molecule/default/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
/etc/pam.d/other: c15fa34ee8bcea3c49fb1ffe0be01d4fe645aed9c498f65a6bc815a6b0ea911ed4d15727e34f93323b113905365565e304e2e608dd9a52663a90443598fb8a0c
/etc/pam.d/remote: c15fa34ee8bcea3c49fb1ffe0be01d4fe645aed9c498f65a6bc815a6b0ea911ed4d15727e34f93323b113905365565e304e2e608dd9a52663a90443598fb8a0c
/etc/pam.d/login: 26e3aa31985d4f900727df89060ad9859ff446dc0e550ce992eb8c4b3dd4e2b945426eae5fb9f9323d5e776d2505404080d4d1b11201c149d23e59857a984da2
/etc/pam.d/sshd: 920002e6ab1b8bf4b466080e1ce1097101f0e1da3b885cc98944fbe25d4d3290146e2bfec5c530fb5763358d2e2a662d0682c20b67e4f008e05f37eab61912a9
/etc/pam.d/sshd: 2c80f1940ee43519b2e48375bf57bc79b09a06d9bfe0124dbc9720b632a4fc8061c965cd08c1caccba30e0233b8fa908b06d0925a4826e2227aac08b248eae4a
/etc/pam.d/su: 2bb407eef69bd412f1564e467d5cdc8fb0d743a583a0e93e119595f8325bea4054055a767aa11cba5fc98328609ed06c7f772e5d9423e65fedda4a39f225dcbf
/etc/issue: 62b3de7ded026a9ada1fccb94344309525fcf13665ec8c1a474e8d55c9c91c7ac137cb68eaa158060db631b6a53eb6e2ede3003442c66cb002cd790fe222ffd0
/etc/issue: 62b3de7ded026a9ada1fccb94344309525fcf13665ec8c1a474e8d55c9c91c7ac137cb68eaa158060db631b6a53eb6e2ede3003442c66cb002cd790fe222ffd0
Expand All @@ -38,7 +38,7 @@
/etc/securetty: 59c89246507c3c6f61ed61ddb2558bb020ce23e5f4b8083b28c2bba487bd3c79382634fa5d936c08808a6558ac03e59fa09e29b578e7f8b5f1c0c1fef5564bdc
/etc/shutdown.allow: cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
/etc/inittab: 02c4acadef92a6bf019e4f36f0bd237599dd4d49303a8063c203367d547cb7f9447b63a5affaebae8519dad999cbcbc5f30e14e29d3cfcc745f0075d9ee7f910
/etc/profile: 30b69da92a6ff90079835e79fd9c87bc12d66483a950fd51908f5446bcca3de1cbef2edfbbd7320e8c63af55d1510eeed9afd716ce0cc757e1367f4182cc238c
#/etc/profile: 30b69da92a6ff90079835e79fd9c87bc12d66483a950fd51908f5446bcca3de1cbef2edfbbd7320e8c63af55d1510eeed9afd716ce0cc757e1367f4182cc238c
/usr/sbin/adduser: 959e6513c44060eed2a94effbeb7c599ea5ef20f25c86017ea9f7f4a33655ea0c52d720cf24fc4e664f29aa69c8c549f4d3695c6b8d699f9c3ab5527fa56142a
/etc/group: 494488aa79c28da48d54b274f3aa9620c92dda2d65d3c377c240209a3be2c49d98fc39150b4a99a4896c1e8f8eb012b7da87d6f544d2db776d879a4500d64db3
/etc/gshadow: 0852bd301f403830731c79e45ede27fbc916e8c04f3593eab406965cca0bbb5e0b671ce3b22ccef610dfc395ee7c1122d88850a3f2f74cc27041a0705226d3d1
Expand All @@ -54,3 +54,12 @@
/etc/modprobe.d/usb-storage.conf: bd63700828774e0936e3b7e1db108fd91d6f97ef75eeb3fc7e0f6efa028c47a491b0d341164276a8dea7a9454997ca55111fb4731a14cd3889c7e8cb4b8ee10a
/etc/logrotate.conf: 0db92e0fd8511205021b766888e1bf7a795273b78e1cd1e9ca6d17a49320a2d9b700383375cef0dd7f4ba28d7897325641dcdc183d7c4802de8ef34e24dc6a5b
/etc/ca-certificates.conf: c7ea2365ff93b99f6b66715fe7c6aa785b5ff592277d43b6d9d75bf4503783db99eb44b49869cbec226dd46b550e901b822785a8531da5c0077dd60599dcfa3e
- name: Check that umask is 077 in /etc/profile
ansible.builtin.lineinfile:
path: /etc/profile
line: umask 077
state: present
regexp: '^umask 077$'
check_mode: yes
register: conf
failed_when: (conf is changed) or (conf is failed)
58 changes: 58 additions & 0 deletions newconfs/pam.d/sshd.Debian
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# PAM configuration for the Secure Shell service

# Standard Un*x authentication.
@include common-auth

# Disallow non-root logins when /etc/nologin exists.
account required pam_nologin.so

# Uncomment and edit /etc/security/access.conf if you need to set complex
# access limits that are hard to express in sshd_config.
# account required pam_access.so

# Standard Un*x authorization.
@include common-account

# SELinux needs to be the first session rule. This ensures that any
# lingering context has been cleared. Without this it is possible that a
# module could execute code in the wrong domain.
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close

# Set the loginuid process attribute.
session required pam_loginuid.so

# Create a new session keyring.
session optional pam_keyinit.so force revoke

# Standard Un*x session setup and teardown.
@include common-session

# Print the message of the day upon successful login.
# This includes a dynamically generated part from /run/motd.dynamic
# and a static (admin-editable) part from /etc/motd.
session optional pam_motd.so motd=/run/motd.dynamic
session optional pam_motd.so noupdate

# Print the status of the user's mailbox upon successful login.
session optional pam_mail.so standard noenv # [1]

# Set up user limits from /etc/security/limits.conf.
session required pam_limits.so

# Read environment variables from /etc/environment and
# /etc/security/pam_env.conf.
session required pam_env.so # [1]
# In Debian 4.0 (etch), locale-related environment variables were moved to
# /etc/default/locale, so read that as well.
session required pam_env.so envfile=/etc/default/locale
# For restricted shell
session [success=ignore default=1] pam_succeed_if.so shell = /bin/rbash
session required pam_env.so envfile=/etc/restricted_env

# SELinux needs to intervene at login time to ensure that the process starts
# in the proper default security context. Only sessions which are intended
# to run in the user's context should be run after this.
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open

# Standard Un*x password updating.
@include common-password
27 changes: 27 additions & 0 deletions newconfs/pam.d/sshd.Slackware
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#%PAM-1.0
# pam_securetty.so is commented out since sshd already does a good job of
# protecting itself. You may uncomment it if you like, but then you may
# need to add additional consoles to /etc/securetty if you want to allow
# root logins on them, such as: ssh, pts/0, :0, etc
#auth required pam_securetty.so
# When using pam_faillock, print a message to the user if the account is
# locked. This lets the user know what is going on, but it also potentially
# gives additional information to attackers:
#auth requisite pam_faillock.so preauth
auth include system-auth
# To set a limit on failed authentications, the pam_faillock module
# can be enabled. See pam_faillock(8) for more information.
#auth [default=die] pam_faillock.so authfail
#auth sufficient pam_faillock.so authsucc
account required pam_nologin.so
account include system-auth
password include system-auth
session include system-auth
session include postlogin
session required pam_loginuid.so
-session optional pam_elogind.so
# For restricted shell
session [success=ignore default=1] pam_succeed_if.so shell = /bin/rbash
session required pam_env.so envfile=/etc/restricted_env
# Polyinstantiated (temp) directories
session required pam_namespace.so
101 changes: 101 additions & 0 deletions tasks/misc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,104 @@
failed_when:
- result.failed
- result.msg != "Destination /etc/ntp.conf does not exist !"

# https://github.com/pyllyukko/harden.yml/wiki/Restricted-shell
- name: rbash
become: true
tags: shells
# Currently we have PAM configs only for Slackware & Debian
when: ansible_distribution == "Slackware" or ansible_distribution == "Debian"
block:
- name: Create a rbash symbolic link
ansible.builtin.file:
src: /bin/bash
dest: /bin/rbash
owner: root
group: root
state: link
- name: Create directories for restricted shell
ansible.builtin.file:
path: '{{ item }}'
state: directory
mode: '0755'
owner: root
group: root
with_items:
- /usr/local/rbin
- /var/empty
- name: Create symbolic links to /usr/local/rbin/
ansible.builtin.file:
src: '{{ item.key }}'
dest: '/usr/local/rbin/{{ item.value }}'
owner: root
group: root
state: link
# Basic set of tools
with_dict:
/bin/cat: cat
/usr/bin/chage: chage
/bin/cp: cp
/bin/df: df
/bin/du: du
/bin/id: id
/bin/ls: ls
/bin/mkdir: mkdir
/bin/mv: mv
/usr/bin/passwd: passwd
/bin/printenv: printenv
/usr/bin/view: rview
/usr/bin/vim: rvim
/bin/uname: uname
/usr/bin/uptime: uptime
/bin/who: who
/usr/bin/sleep: sleep
/usr/bin/chmod: chmod
/usr/bin/rm: rm
register: result
failed_when:
- result.failed
- '"src file does not exist" not in result.msg'
- name: Set PATH in /etc/restricted_env
tags:
- pam
- configuration
ansible.builtin.copy:
dest: /etc/restricted_env
owner: root
group: root
mode: '0644'
content: |
PATH=/usr/local/rbin
- name: Make sure rbash is not in the /etc/shells configuration
ansible.builtin.lineinfile:
path: /etc/shells
state: absent
regexp: '^(/usr)?/bin/rbash$'
- name: Configure rbash stuff into /etc/profile
ansible.builtin.blockinfile:
path: /etc/profile
marker: "# {mark} ANSIBLE MANAGED BLOCK - rbash"
block: |
# This needs to come after the /etc/profile.d stuff to properly restrict PATH
# and to avoid unnecessary error messages.
if [ "$SHELL" = "/bin/rbash" -o "$SHELL" = "/usr/local/bin/rbash" ]
then
export PATH="/usr/local/rbin"
export LESSSECURE=1
# Pagers & VISUAL
export PAGER=/usr/bin/less
export MANPAGER=/usr/bin/less
export SYSTEMD_PAGER=/usr/bin/less
export VISUAL=/usr/local/rbin/rvim
# These need to be set read-only here to prevent user's startup files from modifying them later
typeset -r PATH HISTFILE LESSSECURE IFS PAGER MANPAGER SYSTEMD_PAGER SHELL VISUAL ENV BASH_ENV
# Override the one set at /etc/profile.d/coreutils-dircolors.sh, since that
# uses /bin/ls.
alias ls='ls $LS_OPTIONS'
# Before activating the restrictions, jump to a non-writable directory
cd /var/empty
# Activate the restrictions before user's configuration is being read.
set -r
# Let the user know this is a restricted environment.
shopt restricted_shell
fi
23 changes: 21 additions & 2 deletions tasks/pam.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@
- umask

# ANSSI-BP-028 R55 - Dedicating temporary directories to users
- name: Add pam_namespace to /etc/pam.d/{login,sddm,sshd,xdm} (Slackware)
# sshd is handled by the task below
- name: Add pam_namespace to /etc/pam.d/{login,sddm,xdm} (Slackware)
when: ansible_distribution == "Slackware"
become: true
ansible.builtin.lineinfile:
Expand All @@ -79,7 +80,6 @@
backup: true
insertafter: EOF
with_items:
- sshd
- login
- sddm
- xdm
Expand All @@ -92,6 +92,25 @@
- result.failed
- '"does not exist !" not in result.msg'

# This also relates to restricted shells
# Debian's config from https://salsa.debian.org/ssh-team/openssh/-/blob/master/debian/openssh-server.sshd.pam.in
- name: Copy /etc/pam.d/sshd
when: ansible_distribution == "Slackware" or ansible_distribution == "Debian"
become: true
tags:
- pam
- configuration
- shells
- ssh
- services
ansible.builtin.copy:
src: "{{ playbook_dir }}/newconfs/pam.d/sshd.{{ ansible_distribution }}"
dest: /etc/pam.d/sshd
owner: root
group: root
mode: '0644'
backup: true

- name: Remove nullok from /etc/pam.d/vsftpd (Slackware)
when: ansible_distribution == "Slackware"
become: true
Expand Down
2 changes: 1 addition & 1 deletion templates/sshd_config-Debian.j2
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ X11Forwarding no
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#PermitUserEnvironment no
PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
ClientAliveCountMax 3
Expand Down
6 changes: 3 additions & 3 deletions templates/sshd_config-Slackware.j2
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ GSSAPIAuthentication no
# be allowed through the KbdInteractiveAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via KbdInteractiveAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# the setting of "PermitRootLogin prohibit-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and KbdInteractiveAuthentication to 'no'.
#UsePAM yes
UsePAM yes

#AllowAgentForwarding yes
AllowTcpForwarding no
Expand All @@ -103,7 +103,7 @@ X11Forwarding no
#PrintMotd yes
PrintLastLog yes
TCPKeepAlive yes
#PermitUserEnvironment no
PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
ClientAliveCountMax 3
Expand Down

0 comments on commit bc44a3e

Please sign in to comment.