Linux.System.PAM

This artifact enumerates applicable lines from the files that reside in /etc/PAM.d/. This information can be useful for auditing and compliance purposes, or to identify suspicious activity on Linux systems.

For example, we could use the RecordFilter parameter to check for the presence of pam_exec.so, which can be used within PAM configuration to invoke arbitrary scripts.

From MITRE ATT&CK:

Adversaries may modify pluggable authentication modules (PAM) to access user credentials or enable otherwise unwarranted access to accounts. PAM is a modular system of configuration files, libraries, and executable files which guide authentication for many services. The most common authentication module is PAM_unix.so, which retrieves, sets, and verifies account authentication information in /etc/passwd and /etc/shadow

Adversaries may modify components of the PAM system to create backdoors. PAM components, such as PAM_unix.so, can be patched to accept arbitrary adversary supplied values as legitimate credentials.

Malicious modifications to the PAM system may also be abused to steal credentials. Adversaries may infect PAM resources with code to harvest user credentials, since the values exchanged with PAM components may be plain-text since PAM does not store passwords.


name: Linux.System.PAM

description: |
   This artifact enumerates applicable lines from the files that reside in `/etc/PAM.d/`. This information can be useful for auditing and compliance purposes, or to identify suspicious activity on Linux systems.
   
   For example, we could use the `RecordFilter` parameter to check for the presence of `pam_exec.so`, which can be used within PAM configuration to invoke arbitrary scripts.  

   
   From MITRE ATT&CK:
   
   Adversaries may modify pluggable authentication modules (PAM) to access user credentials or enable otherwise unwarranted access to accounts. PAM is a modular system of configuration files, libraries, and executable files which guide authentication for many services. The most common authentication module is PAM_unix.so, which retrieves, sets, and verifies account authentication information in /etc/passwd and /etc/shadow
   
   Adversaries may modify components of the PAM system to create backdoors. PAM components, such as PAM_unix.so, can be patched to accept arbitrary adversary supplied values as legitimate credentials.
   
   Malicious modifications to the PAM system may also be abused to steal credentials. Adversaries may infect PAM resources with code to harvest user credentials, since the values exchanged with PAM components may be plain-text since PAM does not store passwords.
   
reference:
  - https://linux.die.net/man/5/PAM.d
  - https://attack.mitre.org/techniques/T1556/003/
  - https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1556.003/T1556.003.md
  - https://book.hacktricks.xyz/linux-hardening/linux-post-exploitation#sniffing-logon-passwords-with-PAM
  
type: CLIENT
author: Wes Lambert - @therealwlambert|@weslambert@infosec.exchange

parameters:
  - name: PAMGlob
    default: /etc/pam.d/*
  - name: RecordFilter
    default: .
    description: Filter used for targeting specific records by content
  - name: DateAfter
    type: timestamp
    description: "search for events after this date. YYYY-MM-DDTmm:hh:ssZ"
  - name: DateBefore
    type: timestamp
    description: "search for events before this date. YYYY-MM-DDTmm:hh:ssZ"
    
precondition:
      SELECT OS From info() where OS = 'linux'
      
sources:
  - query: |
      LET DateAfterTime <= if(condition=DateAfter,
        then=timestamp(epoch=DateAfter), else=timestamp(epoch="1600-01-01"))
      LET DateBeforeTime <= if(condition=DateBefore,
        then=timestamp(epoch=DateBefore), else=timestamp(epoch="2200-01-01"))        
      LET PAMGlobList = SELECT Mtime, OSPath
        FROM glob(globs=split(string=PAMGlob, sep=","))
      SELECT * FROM foreach(row=PAMGlobList, 
                    query={ SELECT Mtime, 
                                   OSPath, 
                                   Line AS Record
                            FROM  parse_lines(filename=OSPath) 
                            WHERE Record =~ RecordFilter
                            AND Mtime < DateBeforeTime
                            AND Mtime > DateAfterTime
                            AND NOT Record =~ '^#' 
                            AND NOT Record = ''})