Keyloggers are spyware that monitor and record user keystrokes on endpoints. Some variants relay the recorded data to an external party or attacker, enabling threat actors to exfiltrate user credentials or other sensitive information.

This blog post focuses on detecting Indicators of Compromise (IoC) for keyloggers that utilize living-off-the-land (LOTL) techniques. LOTL is an attack technique where adversaries leverage existing legitimate tools on the victim’s endpoint to perform malicious activities. The MITRE ATT&CK framework labels this attack tactic as Input Capture (T1056.001), since it allows attackers to discreetly intercept the victim’s keystrokes without being detected.

How adversaries leverage LOTL techniques to log keystrokes on Linux endpoints

  • Pluggable Authentication Module (PAM) abuse to log keystrokes: PAM is a modular system of configuration files and libraries that manages authentication for multiple services in Linux. Since the values exchanged with PAM are in plain-text, adversaries may infect PAM resources with malicious code to harvest user credentials. Adversaries can also deactivate PAM modules to tamper with the SSHD configuration to capture the keystrokes in a Linux endpoint.
  • Logging shell history to the system log file: Threat actors may use the PROMPT_COMMAND bash variable or other similar shell variables to configure commands that execute whenever a user runs a shell command. Adversaries can also modify shell configuration to save every new command in shell history to the system’s log file. The log is usually located in /var/log/syslog or /var/log/messages, depending on the Linux distribution.

Infrastructure

We use the following infrastructure to demonstrate the detection of keyloggers using Wazuh.

  • A pre-built, ready-to-use Wazuh OVA 4.7.0 that includes the Wazuh central components (Wazuh server, Wazuh indexer, and Wazuh dashboard). Follow the Virtual Machine (OVA) – Installation guide to download and set up the Wazuh virtual machine.
  • Any Linux endpoint with Wazuh agent 4.7.0 installed and enrolled to the Wazuh server. We use Amazon Linux 2 to simulate the attack and test the SCA policies we create in this blog post. Refer to the Wazuh agent installation guide to install the Wazuh agent.

Configuration

In this section, we show how to configure the Wazuh server and the Wazuh agent to detect Linux keyloggers that utilize LOTL techniques.

Amazon Linux endpoint

The Wazuh Security Configuration Assessment (SCA) module performs checks that validate configuration policies by detecting when legitimate programs on monitored endpoints are poorly configured. We utilize the Wazuh SCA module to detect when legitimate programs are logging keystrokes on Linux endpoints.

We create the SCA policy on the monitored endpoint to detect when adversaries are capturing keystrokes with the use of LOTL techniques.

1. Create a new policy file /var/ossec/etc/sca_detect_linux_keylogger.yml and add the content below to the file:

policy:
  id: "detect_linux_keylogger"
  file: "sca_detect_linux_keylogger.yml"
  name: "System audit to detect keylogger on Linux endpoints"
  description: "Scans to detect potential keyloggers on Linux endpoints."
  references:
    - https://attack.mitre.org/techniques/T1056/001/

requirements:
  title: "Check that the SSH service and password-related files are present on the system"
  description: "Requirements for running the SCA scan against the Unix based systems policy."
  condition: any
  rules:
    - "f:$sshd_file"
    - "f:/etc/passwd"
    - "f:/etc/shadow"

variables:
  $sshd_file: /etc/ssh/sshd_config
  $pam_d_files: /etc/pam.d/common-password /etc/pam.d/passwd-auth /etc/pam.d/system-auth /etc/pam.d/system-auth-ac /etc/pam.d/passwd /etc/pam.d/sshd
  $bash_cfg_files: /root/.bashrc /root/.bash_profile /root/.bash_aliases /home/*/.bashrc /home/*/.bash_profile /home/*/.bash_aliases /etc/skel/.bashrc
  $zsh_cfg_files: /root/.zshrc /root/.zprofile /root/.zsh_aliases /home/*/.zshrc,/home/*/.zprofile /home/*/.zsh_aliases /etc/zsh/zshrc
  $tcsh_cfg_files: /root/.tcshrc /root/.login /root/.cshrc /home/*/.tcshrc /home/*/.login /home/*/.cshrc /etc/csh.cshrc
  $fish_cfg_files: /root/.config/fish/config.fish /root/.config/fish/functions/*.fish /home/*/.config/fish/config.fish /home/*/.config/fish/functions/*.fish /etc/fish/config.fish
  $ksh_cfg_files: /root/.profile /root/.kshrc /home/*/.profile /home/*/.kshrc /etc/profile /etc/kshrc

checks:
  - id: 10030
    title: "PAM abuse to log keystrokes"
    description: "Threat actors may enable the PAM auditing feature to log keystrokes."
    rationale: "By adding the line 'pam_tty_audit.so enable=' to the PAM configuration files, the system is configured to require the pam_tty_audit.so module to log TTY sessions."
    remediation: "Edit the /etc/pam.d/password-auth and /etc/pam.d/system-auth files, to disable the PAM TTY auditing feature."
    compliance:
      - pci_dss: ["2.2.4"]
      - nist_800_53: ["CM.1"]
    condition: none
    rules:
      - 'c:cat $pam_d_files 2>/dev/null -> r:^session \.*pam_tty_audit.so \.*enable='


  - id: 10031
    title: "PAM abuse to log passwords"
    description: "Threat actors may enable the PAM auditing feature to log password."
    rationale: "By a line similar to 'pam_tty_audit.so enable=* log_password' to the PAM configuration files, the system is configured to require the pam_tty_audit.so module to log passwords in TTY sessions."
    remediation: "Edit the /etc/pam.d/password-auth and /etc/pam.d/system-auth files, to disable the PAM TTY password auditing feature."
    compliance:
      - pci_dss: ["2.2.4"]
      - nist_800_53: ["CM.1"]
    condition: none
    rules:
      - 'c:cat $pam_d_files 2>/dev/null -> r:^session \.*pam_tty_audit.so \.*enable=\.*log_password'

  - id: 10032
    title: "Logging shell history to file"
    description: "Threat actors may log shell history to a file they can easily read from, most commonly a log file."
    rationale: "Threat actors utilize shell prompts such as the PROMPT_COMMAND variable, the precmd() function or some other shell feature to log every command executed."
    remediation: "Edit your shell configuration files, and remove configuration lines that attempt to write shell history to another file different from the default shell history file."
    compliance:
      - pci_dss: ["2.2.4"]
      - nist_800_53: ["CM.1"]
    condition: none
    rules:
      - 'c:cat $bash_cfg_files -> r:^PROMPT_COMMAND=\.*history -a'
      - 'c:cat $zsh_cfg_files -> r:^precmd\.*\(\)\.*history -a'
      - 'c:cat $tcsh_cfg_files -> r:^alias precmd\.*history -S'
      - 'c:cat $fish_cfg_files -> r:^function fish_prompt\.*history -h'
      - 'c:cat $ksh_cfg_files -> r:^PS1=\.*history -a'

  - id: 10033
    title: "Known keylogger process"
    description: "Threat actors may utilize known keylogging applications."
    rationale: "Threat actors may use off-the-shelf keylogging applications to log user keystrokes."
    remediation: "Investigate the endpoint, kill the running process, remove the persistence of the keylogger."
    compliance:
      - pci_dss: ["2.2.4"]
      - nist_800_53: ["CM.1"]
    condition: none
    rules:
      - 'c:ps -e -o comm= -> r:^logkeys|^lkl|^uberkey|^thc-vlogger'
      - 'c:ps aux -> r:py.*keylogger'

Where:

  • SCA check ID 10030 determines if adversaries have enabled the PAM auditing feature in a Linux endpoint to log keystrokes.
  • SCA check ID 10031 determines if adversaries have enabled the PAM auditing feature in a Linux endpoint, specifically to log the victim’s password.
  • SCA check ID 10032 determines if adversaries have logged the shell history of a Linux endpoint in the system log file.
  • SCA check ID 10033 determines if adversaries are using any known keylogging application to capture keystrokes in a Linux endpoint.

2. Change the owner and group of the sca_detect_linux_keylogger.yml file to wazuh:

# chown wazuh:wazuh /var/ossec/etc/sca_detect_linux_keylogger.yml

3. Enable the policy by appending the following configuration to the /var/ossec/etc/ossec.conf file on the monitored endpoint:

<ossec_config>
  <sca>
    <enabled>yes</enabled>
    <scan_on_start>yes</scan_on_start>
    <interval>24h</interval>
    <skip_nfs>yes</skip_nfs>
    <policies> 
      <policy>/var/ossec/etc/sca_detect_linux_keylogger.yml</policy>  
    </policies>
  </sca>
</ossec_config>

4. Restart the Wazuh agent to apply the changes:

# systemctl restart wazuh-agent

Simulating attacks on the Linux endpoint

We use the following PoC to simulate the LOTL attack of capturing keystrokes. Perform the following steps on the victim endpoint:

Note: Run the commands below with root privileges.

1. PAM abuse to log keystrokes and passwords

Run the following commands that configure the system to log the victim’s password and keyboard activities in terminal sessions (TTY).

# if sudo test -f /etc/pam.d/password-auth; then sudo cp /etc/pam.d/password-auth /tmp/password-auth.bk; fi;
# if sudo test -f /etc/pam.d/system-auth; then sudo cp /etc/pam.d/system-auth /tmp/system-auth.bk; fi;
# sudo echo "session    required    pam_tty_audit.so enable=* log_password" >> /etc/pam.d/password-auth
# sudo echo "session    required    pam_tty_audit.so enable=* log_password" >> /etc/pam.d/system-auth
  • By adding the line session    required    pam_tty_audit.so enable=* log_password to the PAM configuration files (password-auth and system-auth), the system is configured to require the pam_tty_audit.so module for auditing every TTY session.
  • The enable=* parameter specifies that auditing should be enabled for all users, and the log_password parameter indicates that passwords entered during the session should also be logged.

2. Logging shell history to log file

Run the following command to configure bash shell to save every new command in shell history to the specific Linux distribution log file:

# echo 'PROMPT_COMMAND="history -a >(tee -a ~/.bash_history | logger -t \"$USER[$$] $SSH_CONNECTION \")"' >> ~/.bashrc
  • The PROMPT_COMMAND variable is usually defined in files such as ~/.bashrc for persistence.
  • The history -a command is used to append the current session’s command history to the file ~/.bash_history
  • The tee -a ~/.bash_history command takes the input from the previous command and appends it to ~/.bash_history while also allowing it to be passed to the next command. 
  • The logger -t "$USER[$$] $SSH_CONNECTION" command logs the input received from tee to the system log file with the specified tag.

To start the simulation test, open a new terminal as root and execute the following commands:

# echo "$PROMPT_COMMAND"; echo "testing the simulation"
# cat /var/log/{syslog,messages} | grep "testing the simulation"

3. Known keylogger processes

Attackers frequently use common keyloggers alongside LOTL attack techniques in Linux to stealthily capture sensitive data while leveraging trusted system utilities, thereby avoiding detection.

Some common keyloggers that are widely recognized in Linux endpoints are:

  • LKL captures hardware keyboard port data and converts keycodes to ASCII using a keymap file.
  • Uberkey captures keystrokes directly from the keyboard controller and performs a simple translation.
  • THC-vlogger gives the ability to log keystrokes from all administrator/user sessions via remote sessions and transfer the logged data to a centralized remote server.
  • PyKeylogger is a free open source keylogger designed for personal backup purposes, offering a universal backup solution for all keystrokes.
  • Logkeys keylogger captures all characters and function keys and does not repeat any keys.

Run the following commands to simulate one of the known keylogger processes (LKL):

# cp /usr/bin/sleep ~/lkl; ~/lkl 600 &

Detection results

To view the results immediately, restart the Wazuh agent to trigger the SCA scan which will detect the keylogger IoCs:

# systemctl restart wazuh-agent

Below is an image of SCA results in the Security configuration assessment tab of the Wazuh dashboard when Wazuh detects keylogging activities in a Linux endpoint.

Keyloggers SCA Results

Cleanup commands

At the end of the simulation, follow the steps below to clean up the Linux endpoint:

1. Run the following commands to clean up the simulation of PAM abuse to log keystrokes and passwords from the Linux endpoint:

# if sudo test -f /tmp/password-auth.bk; then sudo cp /tmp/password-auth.bk /etc/pam.d/password-auth; else rm /etc/pam.d/password-auth; fi;
# if sudo test -f /tmp/system-auth.bk; then sudo cp /tmp/system-auth.bk /etc/pam.d/system-auth; else rm /etc/pam.d/system-auth; fi;

2. Run the following commands to clean up the simulation of logging shell history to the system log files from the Linux endpoint:

# unset PROMPT_COMMAND
# sed -i '/PROMPT_COMMAND="history -a >(tee -a ~\/.bash_history \| logger -t \"$USER[$$] $SSH_CONNECTION \")"/d' ~/.bashrc

3. Run the following command to clean up the simulation of the known keylogger process (LKL) from the Linux endpoint:

# rm ~/lkl

4. Restart the Wazuh agent to manually run the SCA scan:

# systemctl restart wazuh-agent

Check the SCA module on the Wazuh dashboard to verify that the cleanup actions are successful.

Detecting Keyloggers

Conclusion

Keyloggers are a common type of spyware that attackers use to capture their victim’s keystrokes, potentially exposing sensitive information such as credentials. In this blog post, we demonstrated how to create custom SCA policies in Wazuh to detect multiple keyloggers in a Linux endpoint using LOTL techniques.

Wazuh is a free, open source SIEM and XDR solution that can monitor and detect malicious activities. To learn more about Wazuh capabilities, check out our documentation, blog posts, and our community for support and updates.

Reference