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.[1]
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.[2][3]
Adversaries may also leverage a Network Device CLI on network devices to disable historical command logging (e.g. no logging).
Threat groups70th percentile · 64% of ATT&CK techniques have fewer threat groups attributed.
2
CampaignsTop 17%
Campaigns83rd percentile · 73% of ATT&CK techniques have fewer campaigns recorded.
6
Tools & malware68th pct
Tools & malware68th percentile · 66% of ATT&CK techniques have fewer tools implementing them.
3
Detection rules54th pct
Detection rules54th percentile · 49% of ATT&CK techniques have fewer detection rules written.
Prevent Command History Logging MITRE reference T1690
70th pctamong all ATT&CK techniques for number of groups
4 groups have been recorded using this technique. Newest first; each entry carries MITRE’s procedure text and a link to the group’s full record. Click a name to filter the rules below.
Has removed PowerShell command history through the use of the PSReadLine module by running the PowerShell command Remove-Item (Get-PSReadlineOption).HistorySavePath.1
Included disabling logging on targeted Cisco ASA appliances.12
2023–2024
All 2 campaigns for this technique
6 software entries are documented implementing this technique. MITRE files each as a tool or as malware; newest first, then by how many groups carry them.
Prevent Command History Logging detection strategy DET0563
MITRE names one behaviour worth catching for this technique and breaks it into 5 analytics, one per platform. Each carries the log sources it needs and the fields you tune per environment.
Detection Strategy for Defense Impairment via Prevent Command History Logging across OS platforms.
Enterprise
5 platforms
AN1555 · Linux
Detection of environment variable tampering (HISTFILE, HISTCONTROL, HISTFILESIZE) and absence of expected bash history writes. Correlation of unset or zeroed history variables with active shell sessions is indicative of adversarial evasion.
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
execve calls modifying HISTFILE or HISTCONTROL via unset/export
Tunable fields
MITRE calls these the analytic’s mutable elements: the thresholds and filters you set for your own environment.
Field
What you tune
MonitoredUsers
Specific accounts or groups where history logging must always be enforced.
TimeWindow
Correlation period to detect unset/export of history variables during active shells.
AN1556 · macOS
Detection of bash/zsh history suppression via HISTFILE/HISTCONTROL manipulation and absence of ~/.bash_history updates. Observing environment variable changes tied to terminal processes is a strong indicator.
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
MITRE calls these the analytic’s mutable elements: the thresholds and filters you set for your own environment.
Field
What you tune
ShellProfiles
Different shells (bash, zsh, fish) may require customized monitoring for history tampering.
AN1557 · Windows
Detection of PowerShell history suppression using Set-PSReadLineOption with SaveNothing or altered HistorySavePath. Correlating these options with PowerShell usage highlights adversarial evasion attempts.
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
MITRE calls these the analytic’s mutable elements: the thresholds and filters you set for your own environment.
Field
What you tune
AllowedPaths
List of acceptable PowerShell history save paths for baseline comparison.
AN1558 · ESXi
Detection of unset HISTFILE or modified history variables in ESXi shell sessions. Correlation of suspicious shell sessions with no recorded commands despite active usage.
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
MITRE calls these the analytic’s mutable elements: the thresholds and filters you set for your own environment.
Field
What you tune
AdminSessions
Differentiate root/admin shell sessions from adversarial misuse of ESXi shell.
AN1559 · Network Devices
Detection of CLI commands that disable history logging such as 'no logging'. Anomalous lack of new commands in session logs while activity persists is a strong signal.
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
Make sure that the HISTCONTROL environment variable is set to “ignoredups” instead of “ignoreboth” or “ignorespace”.
Tests12Executorsbash 5 · sh 4 · manual 1 · command_prompt 1 · powershell 1Need elevation2 of 12Have prerequisites0Have cleanup9Platformslinux, macos, windows
#
Test
Platform
Executor
Elevation
Prereqs
Cleanup
Ref
01
Disable history collection
linux, macos
sh
—
—
—
Disables history collection in shells
Inputs
Name
Description
Type
Default Value
evil_command
Command to run after shell history collection is disabled
string
whoami
Attack Commandsrun with sh
export HISTCONTROL=ignoreboth
#{evil_command}
GUID4eafdb45-0f79-4d66-aa86-a3e2c08791f5
02
Disable history collection (freebsd)
linux
sh
—
—
—
Disables history collection in shells
Inputs
Name
Description
Type
Default Value
evil_command
Command to run after shell history collection is disabled
string
whoami
Attack Commandsrun with sh
export HISTSIZE=0
#{evil_command}
GUIDcada55b4-8251-4c60-819e-8ec1b33c9306
03
Mac HISTCONTROL
macos, linux
manual
—
—
—
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
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.
Attack Commandsrun with bash
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
Cleanup Commands
mv -f $HISTFILE.OLD $HISTFILE
GUID878794f7-c511-4199-a950-8c28b3ed8e5b
05
Setting the HISTCONTROL environment variable
linux
bash
—
—
Yes
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
Attack Commandsrun with bash
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
Cleanup Commands
export HISTCONTROL=$(echo $TEST)
GUID10ab786a-028e-4465-96f6-9e83ca6c5f24
06
Setting the HISTFILESIZE environment variable
linux
bash
—
—
Yes
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.
Attack Commandsrun with bash
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
Cleanup Commands
export HISTCONTROL=$(echo $TEST)
GUID5cafd6c1-2f43-46eb-ac47-a5301ba0a618
07
Setting the HISTSIZE environment variable
linux
sh
—
—
Yes
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.
Attack Commandsrun with sh
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
Cleanup Commands
export HISTSIZE=100
GUID386d3850-2ce7-4508-b56b-c0558922c814
08
Setting the HISTFILE environment variable
linux
bash
—
—
Yes
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.
Attack Commandsrun with bash
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
Cleanup Commands
export HISTFILE=$(echo $TEST)
GUIDb3dacb6c-a9e3-44ec-bf87-38db60c5cad1
09
Setting the HISTFILE environment variable (freebsd)
linux
sh
—
—
Yes
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.
Attack Commandsrun with sh
echo $HISTFILE
export HISTFILE="/dev/null"
if [ $(echo $HISTFILE) == "/dev/null" ]; then echo "\$HISTFILE is /dev/null"; fi
Cleanup Commands
export HISTFILE=~/.sh_history
GUIDf7308845-6da8-468e-99f2-4271f2f5bb67
10
Setting the HISTIGNORE environment variable
linux
bash
—
—
Yes
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.
Attack Commandsrun with bash
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
Cleanup Commands
unset HISTIGNORE
GUIDf12acddb-7502-4ce6-a146-5b62c59592f1
11
Disable Windows Command Line Auditing using reg.exe
windows
command_prompt
Required
—
Yes
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
Attack Commandsrun with command_promptelevation required (root or admin)
Disable Windows Command Line Auditing using Powershell Cmdlet
windows
powershell
Required
—
Yes
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
Attack Commandsrun with powershellelevation required (root or admin)
This detection identifies changes to the syslog configuration on an ESXi host using esxcli, which may indicate an attempt to disrupt log collection and evade detection.