Linux PAM Framework
Tags: linux, bash, security
Published: 2023-02-15 05:44:07

## Introduction

> Linux PAM (Pluggable Authentication Modules) is a framework that provides a flexible and modular approach to authentication, authorization, and other security-related tasks in Linux-based systems

With PAM, authentication and authorization tasks can be delegated to various modules, each of which is responsible for a specific aspect of the process, such as password validation, smart card authentication, biometric authentication, and more

💡 The concept of PAM library is similar to the DLL library in Windows

## How does it work?

- User attempts to log in or perform an action requiring authentication
- System checks if the service uses PAM
- PAM invokes the appropriate PAM stack
- Each module in the stack performs a specific task
- If all modules succeed, access is granted
- User is logged in or action is performed


![PAM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/havh97jqj6cu5h2as1fp.png)

## PAM Library paths used

- **/etc/pam.d** => The config files for programs using the PAM library are present under this path
- **/usr/lib64/security** => Authentication modules provided by PAM library
- **/etc/security** => This contains config files required to execute PAM modules

## PAM Types

- **Account**: Determines if the user is allowed access based on account properties
- **Authentication**: Verifies the user's identity with a credential, such as a password
- **Password**: Changes the user's password and enforces password policies
- **Session**: Sets up and tears down a user's session and performs related tasks

## PAM Controls

- **Required**: If the module fails, the authentication process is immediately aborted
- **Requisite**: If the module fails, the authentication process is immediately aborted, but a failure is not logged
- **Sufficient**: If the module succeeds, the authentication process is immediately considered successful and no further modules are executed

###💡 We also have:

**Module-paths**: PAM modules are loadable libraries, and the module-paths specify the location of these libraries in the system.

**Module-arguments**: PAM modules can take arguments that are specified in the PAM configuration file. These arguments are used to customize the behavior of the module or provide additional information to the module. The syntax for specifying module arguments is module-type control-flag module-path [module-arguments].

---

## Hands on using `rootok.so`

We can do some simple tests using the `/etc/pam.d/su` config file


```bash
# Adding a user with password
useradd s1
passwd s1

# Using the 'su' command to shift to s1 user
su s1
```

This won't require any authentication as we are the 'root' user

But what if we change a setting here?
```bash
vi /etc/pam.d/su

#%PAM-1.0
#auth            sufficient      pam_rootok.so
# Uncomment the following line to implicitly trust users in the "wheel" group.
#auth           sufficient      pam_wheel.so trust use_uid
# Uncomment the following line to require a user to be in the "wheel" group.
#auth           required        pam_wheel.so use_uid
auth            substack        system-auth
auth            include         postlogin
account         sufficient      pam_succeed_if.so uid = 0 use_uid quiet
account         include         system-auth
password        include         system-auth
session         include         system-auth
session         include         postlogin
session         optional        pam_xauth.so
```

In this file, we can comment out the second line and then test again

```bash
su s1
password:
```

This now requires a password as it ignores the 'auth sufficient' line for the root user

💡 We can test using `required` or `requisite` instead of `sufficient` in the second line as well
 
-> `required` will let the root user shift users using password but won't let normal users to shift even when the password is right
-> `requisite` will let the user shift users using password but won't let normal users to shift at all, not letting the normal user to write the password at all


Next, we will look at line 3 and 4

---

## Hands on using `wheel`

```bash
      3 auth            sufficient      pam_wheel.so trust use_uid
      4 auth            required        pam_wheel.so use_uid
```
> Commenting out the second line and the 4th line

the `pam_wheel.so trust use_uid` line allows users in the "wheel" group to execute privileged commands without a password prompt, and determines group membership based on the user's UID

the `pam_wheel.so use_uid` line configures PAM to use UID-based group membership to determine if a user is a member of the "wheel" group and is allowed to execute privileged commands without a password prompt

We can check the wheel group

```bash
cat /etc/group | grep wheel
wheel:x:10:
```

Adding a user into this group

```bash
usermod -G wheel user1

# Confirming
cat /etc/group | grep wheel
wheel:x:10:itbank
```

Now if we shift to the user1, it will ask for the password and for the user1, it won't need any authentication for shifting to the root user which isn't the optimal situation.

> Uncomment the second line and erase the 'trust' from the 3rd line

```bash
      2 auth            sufficient      pam_rootok.so
      3 auth            sufficient      pam_wheel.so use_uid
      4 #auth           required        pam_wheel.so use_uid
```

Now the root user can shift to user1 without any password while the user1 has to use a password to shift to root user

So now what if we want the following 

-> root > user1 (no password)
-> user1 > root  (needs password)
-> user1 > user2 (no password)

For the config file `/etc/pam.d/su`

```bash
      2 auth            sufficient      pam_rootok.so
      3 auth            required        pam_wheel.so trust use_uid
      4 auth            sufficient      pam_succeed_if.so uid >= 1000 quiet
```

Here the 4th line allows the PAM stack to silently return a success value if the user's UID is greater than or equal to 1000

The above configuration will allow the user1 to shift to user2 but if we try to shift from user2 to user1, it won't let us even using the password when prompted

> 👉 Reverse changes inside `/etc/pam.d/su`

---

## `/etc/pam.d/system-auth`

To fix this we do some edits in the following config file,

```bash
vi /etc/pam.d/system-auth

#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth        required      pam_faildelay.so delay=2000000
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
auth        required      pam_deny.so

account     required      pam_unix.so
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 1000 quiet
account     required      pam_permit.so

password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
-session     optional      pam_systemd.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so
```

We need to change some lines here,

```bash
auth        required      pam_env.so
auth        required      pam_faildelay.so delay=2000000
auth        required      pam_unix.so nullok try_first_pass
auth        sufficient    pam_succeed_if.so user != root quiet_success
auth        sufficient    pam_succeed_if.so user = user1 use_uid quiet_success
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
auth        required      pam_deny.so
```

Now,

- root user can shift to user1 and all other users without password. 
- user1 can shift to other users with their passwords
- other users can shift to user1 with user1 password
- **user1** has the only access to root user using the root user password
- other users **cannot** shift to root user

So we can actually implement this for remote access,
 
**SSH ->** `PermitRootLogin  NO`
**PAM ->** The above configuration

This will make, 

`SSH => user1 login -> root user (to work as a root user)`

✨ This will tighten the security more than normal SSH into the server as the root user