Navigate back to the homepage

Hiding Your Tracks Bash History

January 20th, 2020 · 2 min read

Different techniques for preventing commands from being stored in $HISTFILE

❯ Bash history

Bash maintains the list of commands internally in memory while it’s running. They are written into $HISTFILE (i.e, ~/.bash_history) when a user logs off.

1❯ echo $HISTFILE

This post is a cheat sheet for common methods attackers use to hide commands from being saved in the history file or in memory

❯ Leading Space

Might not be enabled by default in some distros

Starting each command with a leading space character

1❯ echo "hello"
3❯ echo "ritsec"
5❯ history
6 1 ls
7 2 echo "hello"
8 3 history

Notice that the command $echo "hello" was saved history unlike the commas with a leading space $ echo "ritsec". This is possible because of HISTCONTROL environment variable

1❯ head -2 /etc/os-release
2 NAME="Ubuntu"
3 VERSION="18.04.3 LTS (Bionic Beaver)"
5 ignoredups:ignorespace


The HISTFILE environment variable specifies bash history file

1❯ man bash
3 The name of the file in which command history is saved (see HISTORY be‐
4 low). The default value is ~/.bash_history. If unset, the command his‐
5 tory is not saved when a shell exits.
6 the value of HISTIGNORE. The pattern matching honors the setting of the
7 extglob shell option.
1❯ echo $HISTFILE

To avoid recording commands to the file in $HISTFILE set HISTFILE value to /dev/null

1❯ HISTFILE=/dev/null
3❯ export HISTFILE=/dev/null

❯ Using unset

1man bash
3 Remove variable or function names

We can use unset to remove the variable HISTFILE for the current session

1❯ echo $HISTFILE
3❯ unset HISTFILE
4❯ echo $HISTFILE

Note that it will only effect the current session. If you start another session the variable HISTFILE will still be set unlike changing $HISTILE value to /dev/null


Notice the distinction between file: on disk - and list: in memory.

HISTSIZE is the number of lines or commands that are stored in memory in a history list while your bash session is ongoing.

1❯ man bash
4 The number of commands to remember in the command history (see HISTORY
5 below). If the value is 0, commands are not saved in the history list.
6 Numeric values less than zero result in every command being saved on the
7 history list (there is no limit). The shell sets the default value to
8 500 after reading any startup files.

In order to remove all commands from to the history list in memory change the size to 0

1❯ echo $HISTSIZE
3❯ HISTSIZE=0 # OR export HISTSIZE=0
4❯ echo $HISTSIZE

HISTFILESIZE is the number of lines or commands that

  • are allowed in the history file at startup time of a session, and
  • are stored in the history file at the end of your bash session for use in future sessions.
1❯ man bash
4 The maximum number of lines contained in the history file. When this
5 variable is assigned a value, the history file is truncated, if neces‐
6 sary, to contain no more than that number of lines by removing the oldest
7 entries. The history file is also truncated to this size after writing
8 it when a shell exits. If the value is 0, the history file is truncated
9 to zero size. Non-numeric values and numeric values less than zero in‐
10 hibit truncation. The shell sets the default value to the value of HIST‐
11 SIZE after reading any startup files.

❯ The Set & Shopt Builtin

The set builtin allows you to change the values of shell options and set the positional parameters, or to display the names and values of shell variables. Using set we can avoid recording new commands to the history list in memory. And, because it’s not being saved in memory, it can not be recorded to file

  • -o option-name: Set the option corresponding to option-name

The option name here is history and its enabled by default. Using ‘+’ rather than ‘-’ causes these options to be turned off

1❯ set +o history

Using ‘-’ we can enable it again;

1❯ set -o history

Alternatively the shopt builtin command can be used shopt builtin command allows you to change additional shell optional behavior.

  • -u Disable (unset) each optname. -o` Restricts the values of optname to be those defined for the -o option to the set builtin
1❯ shopt -ou history

Re-enable it using the -s flag;

  • -s Enable (set) each optname.
1❯ shopt -os history

❯ Clearing the History

Rather than disabling command history, we can clear the history on the current bash shell by simply using the history command with the -c (clear) flag

1❯ history -c

Then, to make certain the changes are written to disk, we need to tell the history command to write to disk with the -w flag

1❯ history -w

This only clears the history of the current shell. Commands run in other shells will remain on disk.

❯ Shredding the History

1❯ man shred
2 shred - overwrite a file to hide its contents, and optionally delete it

The shred command shreds the target file making it unreadable

1❯ cat $HISTFILE
3history -w
4❯ shred $HISTFILE
5❯ cat $HISTFILE
6 ,Iç!hù2g2V?ƥf[Æ{L´w٘Ì˿vCÓ/Zs
7PìPõä{K{ëúJ :i6­ÚûR܈?ÄñW?äÆn6»¬ËoûD;NGÖËÓâ¯TRú&Í__tÇÙ
9 OËã

After using the shred command the history file contains bunch of binary data that is nonsense.

The fact that the file is shredded may in itself be considered evidence of malicious activity. We can eliminate even that by combining the shred command with the -zu flags

  • -u deallocate and remove file after overwriting
  • -z a final overwrite with zeros to hide shredding
1❯ cat $HISTFILE
3history -w❯ docker exec -ti 6e0aec73e61c bash
5❯ shred -zu $HISTFILE
6❯ cat $HISTFILE
7cat: /root/.bash_history: No such file or directory

❯ Killing Bash Process

Using the kill command we can exit the session without saving commands in memory to disk using;

1❯ kill -9 $$

thanks to @ReigningShells

❯ Using More

We can hide a command from being saved in memory using more ability to excute commands by prepending them with !

  • !<cmd> or :!<cmd> Execute <cmd> in a subshell
1❯ ps -aef | more
3root 1 0 0 Jan20 ? 00:00:03 /sbin/init
4root 2 0 0 Jan20 ? 00:00:00 [kthreadd]
5root 3 2 0 Jan20 ? 00:00:00 [rcu_gp]
7!echo "thanks @13_0_0_0_0"
8thanks @13_0_0_0_0

At the more prompt type ! or :! followed by your command.

This same technique can be used with other GTFOBIN like vim

More articles from SecBytes

SwagShop Hack The Box Writeup

Complete walkthrough for SwagShop on Hack The Box

September 28th, 2019 · 2 min read

The Hunt for LOLBAS

Using Powershell to Hunt for LOLBAS

July 13th, 2019 · 2 min read
© 2019–2020 SecBytes
Link to $ to $