Home/ATT&CK Technique/Prevent Command History Logging
ATT&CK Technique

Prevent Command History Logging

T1690 · defense-impairment

Adversaries may impair command history logging to hide commands they run on a compromised system. Various command interpreters keep track of the commands users type in their terminal so that users can retrace what they have done. On Linux and macOS, command history is tracked in a file pointed to by the environment variable HISTFILE.

When a user logs off a system, this information is flushed to a file in the user's home directory called ~/.bash_history. The HISTCONTROL environment variable keeps track of what should be saved by the history command and eventually into the ~/.bash_history file when a user logs out. HISTCONTROL does not exist by default on macOS, but can be set by the user and will be respected. The HISTFILE environment variable is also used in some ESXi systems.

Adversaries may clear the history environment variable (unset HISTFILE) or set the command history size to zero (export HISTFILESIZE=0) to prevent logging of commands. Additionally, HISTCONTROL can be configured to ignore commands that start with a space by simply setting it to "ignorespace". HISTCONTROL can also be set to ignore duplicate commands by setting it to "ignoredups". In some Linux systems, this is set by default to "ignoreboth" which covers both of the previous examples.

This means that " ls" will not be saved, but "ls" would be saved by history. Adversaries can abuse this to operate without leaving traces by simply prepending a space to all of their terminal commands. On Windows systems, the PSReadLine module tracks commands used in all PowerShell sessions and writes them to a file ($env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt by default).

Adversaries may change where these logs are saved using Set-PSReadLineOption -HistorySavePath {File Path}. This will cause ConsoleHost_history.txt to stop receiving logs. Additionally, it is possible to turn off logging to this file using the PowerShell command Set-PSReadlineOption -HistorySaveStyle SaveNothing.

Adversaries may also leverage a Network Device CLI on network devices to disable historical command logging (e.g. no logging).

ESXiLinuxmacOSNetwork DevicesWindows

Atomic Tests

12
Executable Atomic Red Team test cases for exercising this technique in a lab. Copy a command, run it on the listed platform, confirm your detections fire.
shlinux, macosDisable history collection
Disables history collection in shells
export HISTCONTROL=ignoreboth
#{evil_command}
shlinuxDisable history collection (freebsd)
Disables history collection in shells
export HISTSIZE=0
#{evil_command}
manualmacos, linuxMac HISTCONTROL
The HISTCONTROL variable is set to ignore (not write to the history file) command that are a duplicate of something already in the history and commands that start with a space. This atomic sets this variable in the current session and also writes it to the current user's ~/.bash_profile so that it will apply to all future settings as well. https://www.linuxjournal.com/content/using-bash-history-more-efficiently-histcontrol
bashlinuxClear bash history
An attacker may clear the bash history cache and the history file as their last act before logging off to remove the record of their command line activities. In this test we use the $HISTFILE variable throughout to 1. confirms the $HISTFILE variable is set 2. echo "" into it 3..5 confirm the file is empty 6 clear the history cache 7. confirm the history cache is empty. This is when the attacker would logoff.
cp $HISTFILE $HISTFILE.OLD
if ((${#HISTFILE[@]})); then echo $HISTFILE; fi
echo "" > $HISTFILE
if [ $(wc -c <$HISTFILE) -gt 1 ]; then echo "$HISTFILE is larger than 1k"; fi
ls -la $HISTFILE 
cat $HISTFILE
history -c 
if [ $(history |wc -l) -eq 1 ]; then echo "History cache cleared"; fi
bashlinuxSetting the HISTCONTROL environment variable
An attacker may exploit the space before a command (e.g. " ls") or the duplicate command suppression feature in Bash history to prevent their commands from being recorded in the history file or to obscure the order of commands used. In this test we 1. sets $HISTCONTROL to ignoreboth 2. clears the history cache 3. executes ls -la with a space in-front of it 4. confirms that ls -la is not in the history cache 5. sets $HISTCONTROL to erasedups 6. clears the history cache 7..9 executes ls -la $HISTFILE 3 times 10. confirms that their is only one command in history
TEST=$(echo $HISTCONTROL)
if [ "$HISTCONTROL" != "ignoreboth" ]; then export HISTCONTROL="ignoreboth"; fi
history -c 
ls -la $HISTFILE # " ls -la $HISTFILE"
if [ $(history |wc -l) -eq 1 ]; then echo "ls -la is not in history cache"; fi
if [ "$HISTCONTROL" != "erasedups" ]; then export HISTCONTROL="erasedups"; fi
history -c 
ls -la $HISTFILE
ls -la $HISTFILE
ls -la $HISTFILE
if [ $(history |wc -l) -eq 2 ]; then echo "Their is only one entry for ls -la $HISTFILE"; fi
bashlinuxSetting the HISTFILESIZE environment variable
An Adversary may set the bash history files size environment variable (HISTFILESIZE) to zero to prevent the logging of commands to the history file after they log out of the system. Note: we don't wish to log out, so we are just confirming the value of HISTFILESIZE. In this test we 1. echo HISTFILESIZE 2. set it to zero 3. confirm that HISTFILESIZE is set to zero.
TEST=$(echo $HISTFILESIZE)
echo $HISTFILESIZE
export HISTFILESIZE=0
echo "runnning some commands to populate the history"
whoami
groups
if [ $(echo $HISTFILESIZE) -eq 0 ]; then echo "\$HISTFILESIZE is zero"; else HIST_LENGHT=$(wc -l $HISTFILE); echo "\$HISTFILESIZE is not zero, history lenght is $HIST_LENGHT";  fi
shlinuxSetting the HISTSIZE environment variable
An Adversary may set the sh history files size environment variable (HISTSIZE) to zero to prevent the logging of commands to the history file after they log out of the system. Note: we don't wish to log out, so we are just confirming the value of HISTSIZE. In this test we 1. echo HISTSIZE 2. set it to zero 3. confirm that HISTSIZE is set to zero.
echo $HISTSIZE
export HISTSIZE=0
echo "runnning some commands to populate the history"
whoami
groups
if [ $(echo $HISTSIZE) -eq 0 ]; then echo "\$HISTSIZE is zero"; else HIST_LENGTH=$(wc -l $HISTFILE); echo "\$HISTSIZE is not zero, history size is $HIST_LENGTH";  fi
bashlinuxSetting the HISTFILE environment variable
An Adversary may clear, unset or redirect the history environment variable HISTFILE to prevent logging of commands to the history file after they log out of the system. Note: we don't wish to log out, so we are just confirming the value of HISTFILE. In this test we 1. echo HISTFILE 2. set it to /dev/null 3. confirm that HISTFILE is set to /dev/null.
TEST=$(echo $HISTFILE)
echo $HISTFILE
export HISTFILE="/dev/null"
echo "runnning some commands to populate the history"
whoami
groups
if [ $(echo $HISTFILE) == "/dev/null" ]; then echo "\$HISTFILE is /dev/null"; else HIST_LENGHT=$(wc -l $HISTFILE); echo "\$HISTFILE is not /dev/null, history lenght is $HIST_LENGHT";  fi
shlinuxSetting the HISTFILE environment variable (freebsd)
An Adversary may clear, unset or redirect the history environment variable HISTFILE to prevent logging of commands to the history file after they log out of the system. Note: we don't wish to log out, so we are just confirming the value of HISTFILE. In this test we 1. echo HISTFILE 2. set it to /dev/null 3. confirm that HISTFILE is set to /dev/null.
echo $HISTFILE
export HISTFILE="/dev/null"
if [ $(echo $HISTFILE) == "/dev/null" ]; then echo "\$HISTFILE is /dev/null"; fi
bashlinuxSetting the HISTIGNORE environment variable
An Adversary may take advantage of the HISTIGNORE environment variable either to ignore particular commands or all commands. In this test we 1. set HISTIGNORE to ignore ls, rm and ssh commands 2. clear this history cache 3..4 execute ls commands 5. confirm that the ls commands are not in the history cache 6. unset HISTIGNORE variable 7.. same again, but ignoring ALL commands.
if ((${#HISTIGNORE[@]})); then echo "\$HISTIGNORE = $HISTIGNORE"; else export HISTIGNORE='ls*:rm*:ssh*'; echo "\$HISTIGNORE = $HISTIGNORE"; fi
history -c 
ls -la $HISTFILE
ls -la ~/.bash_logout
if [ $(history |wc -l) -eq 1 ]; then echo "ls commands are not in history"; fi
unset HISTIGNORE
if ((${#HISTIGNORE[@]})); then echo "\$HISTIGNORE = $HISTIGNORE"; else export HISTIGNORE='*'; echo "\$HISTIGNORE = $HISTIGNORE"; fi
history -c 
whoami
groups
if [ $(history |wc -l) -eq 0 ]; then echo "History cache is empty"; fi
command_promptelevatedwindowsDisable Windows Command Line Auditing using reg.exe
In Windows operating systems, command line auditing is controlled through the following registry value: Registry Path: HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit Registry Value: ProcessCreationIncludeCmdLine_Enabled When command line auditing is enabled, the system records detailed information about command execution, including the command executed, the user account responsible for executing the command, and the timestamp of the execution. This information is crucial for security monitoring and forensic analysis, as it helps organizations detect and investigate unauthorized or malicious activities within their systems. By default, command line auditing may not be enabled in Windows systems, and administrators must manually configure the appropriate registry settings to activate it. Conversely, attackers may attempt to tamper with these registry keys to disable command line auditing, as part of their efforts to evade detection and cover their tracks while perpetrating malicious activities. Because this attack executes reg.exe using a command prompt, this attack can be detected by monitoring both: Process Creation events for reg.exe (Windows Event ID 4688, Sysmon Event ID 1) Registry events (Windows Event ID 4657, Sysmon Event ID 13) Read more here: https://securitydatasets.com/notebooks/atomic/windows/defense_evasion/SDWIN-220703123711.html
reg add HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit /v ProcessCreationIncludeCmdLine_Enabled /t REG_DWORD /d 0 /f
powershellelevatedwindowsDisable Windows Command Line Auditing using Powershell Cmdlet
In Windows operating systems, command line auditing is controlled through the following registry value: Registry Path: HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit Registry Value: ProcessCreationIncludeCmdLine_Enabled When command line auditing is enabled, the system records detailed information about command execution, including the command executed, the user account responsible for executing the command, and the timestamp of the execution. This information is crucial for security monitoring and forensic analysis, as it helps organizations detect and investigate unauthorized or malicious activities within their systems. By default, command line auditing may not be enabled in Windows systems, and administrators must manually configure the appropriate registry settings to activate it. Conversely, attackers may attempt to tamper with these registry keys to disable command line auditing, as part of their efforts to evade detection and cover their tracks while perpetrating malicious activities. Because this attack runs a Powershell cmdlet, this attack can be detected by monitoring both: Powershell Logging (Windows Powershell Event ID 400, 800, 4103, 4104) Registry events (Windows Event ID 4657, Sysmon Event ID 13) Read more here: https://securitydatasets.com/notebooks/atomic/windows/defense_evasion/SDWIN-220703123711.html https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/new-itemproperty?view=powershell-7.4#example-2-add-a-registry-entry-to-a-key
New-ItemProperty -Path "HKLM:Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit" -Name "ProcessCreationIncludeCmdLine_Enabled" -Value 0 -PropertyType DWORD -Force -ErrorAction Ignore

Mitigations

2
MITRE ATT&CK mitigations - vendor-agnostic guidance for reducing exposure to this technique.
M1028Operating System Configuration

Operating System Configuration involves adjusting system settings and hardening the default configurations of an operating system (OS) to mitigate adversary exploitation and prevent abuse of system functionality. Proper OS configurations address security vulnerabilities, limit attack surfaces, and ensure robust defense against a wide range of techniques.

Disable Unused Features
  • Turn off SMBv1, LLMNR, and NetBIOS where not needed.
  • Disable remote registry and unnecessary services.
Enforce OS-level Protections
  • Enable Data Execution Prevention (DEP), Address Space Layout Randomization (ASLR), and Control Flow Guard (CFG) on Windows.
  • Use AppArmor or SELinux on Linux for mandatory access controls.
Secure Access Settings
  • Enable User Account Control (UAC) for Windows.
  • Restrict root/sudo access on Linux/macOS and enforce strong permissions using sudoers files.
File System Hardening
  • Implement least-privilege access for critical files and system directories.
  • Audit permissions regularly using tools like icacls (Windows) or getfacl/chmod (Linux/macOS).
Secure Remote Access
  • Restrict RDP, SSH, and VNC to authorized IPs using firewall rules.
  • Enable NLA for RDP and enforce strong password/lockout policies.
Harden Boot Configurations
  • Enable Secure Boot and enforce UEFI/BIOS password protection.
  • Use BitLocker or LUKS to encrypt boot drives.
Regular Audits
  • Periodically audit OS configurations using tools like CIS Benchmarks or SCAP tools.
Tools for Implementation Windows
  • Microsoft Group Policy Objects (GPO): Centrally enforce OS security settings.
  • Windows Defender Exploit Guard: Built-in OS protection against exploits.
  • CIS-CAT Pro: Audit Windows security configurations based on CIS Benchmarks.
Linux/macOS
  • AppArmor/SELinux: Enforce mandatory access controls.
  • Lynis: Perform comprehensive security audits.
  • SCAP Security Guide: Automate configuration hardening using Security Content Automation Protocol.
Cross-Platform
  • Ansible or Chef/Puppet: Automate configuration hardening at scale.
  • OpenSCAP: Perform compliance and configuration checks.
M1039Environment Variable Permissions

Restrict the modification of environment variables to authorized users and processes by enforcing strict permissions and policies. This ensures the integrity of environment variables, preventing adversaries from abusing or altering them for malicious purposes.

Restrict Write Access
  • Use Case: Set file system-level permissions to restrict access to environment variable configuration files (e.g., .bashrc, .bash_profile, .zshrc, systemd service files).
  • Implementation: Configure /etc/environment or /etc/profile on Linux systems to only allow root or administrators to modify the file.
Secure Access Controls
  • Use Case: Limit access to environment variable settings in application deployment tools or CI/CD pipelines to authorized personnel.
  • Implementation: Use role-based access control (RBAC) in tools like Jenkins or GitLab to ensure only specific users can modify environment variables.
Restrict Process Scope
  • Use Case: Configure policies to ensure environment variables are only accessible to the processes they are explicitly intended for.
  • Implementation: Use containerized environments like Docker to isolate environment variables to specific containers and ensure they are not inherited by other processes.
Audit Environment Variable Changes
  • Use Case: Enable logging for changes to critical environment variables.
  • Implementation: Use auditd on Linux to monitor changes to files like /etc/environment or application-specific environment files.

Detection Coverage

1/6 layers
Coverage across standard detection surfaces. Rows marked none have no rule of that type mapped. Some are real blind spots worth closing; others are simply not applicable to this technique (e.g. YARA matches malware files, not network behaviour).
Behavioral / log (Sigma) 1
Analytics (MITRE CAR) none
Runtime / container (Falco) none
File / malware (YARA) none
Network (Suricata/Snort) none
Vuln scan (Nuclei) none
Intelligence Graph · click any node to traverse
CVETechnique ActorTool Family
drag to reposition · click any node to traverse · button top-right enlarges
External lookups - second-class, for what we don’t hold ourselves
Vulnerabilities
CISA KEV catalog
CWE weaknesses
CAPEC attack patterns
Package vulnerabilities
Threat intelligence
Threat actors
Tools & malware
ATT&CK techniques
IOCs
Detection & defense
Sigma rules
YARA rules
Atomic Red Team tests
D3FEND countermeasures
Compliance
NIST 800-53
ISO 27001:2022
SOC 2 TSC
PCI-DSS v4.0
CIS Controls v8.1
About
All capabilities
Live statistics
Data sources
Privacy policy
Terms of service
threatengine.sh  ·  Open-source threat intelligence platform  ·  100+ authoritative sources  ·  Every fact traces to its origin