The history tools built into the bash shell are rather powerful and a great source of information about what has been done to a system. One thing we can do to make these even more useful is add them as a data source in Splunk. While imperfect (see caveats below), this can be helpful in demonstrating that your systems are well-monitored for activity performed by users.
If you were going to do this, you might consider something as simple as:
[monitor:///home] whitelist=\.bash_history$ disabled=false
This is a good starting point, but it suffers from some issues:
- Recursively walking all of /home to find just a few small files can be expensive
- Users outside of /home are not seen
- The .bash_history file does not have timestamps, so you’ll get a _time equal to the index time
We can do better. Bash gives us lots of options to change how its history works. Let’s try this snippet in /usr/local/bin/bash-history.sh:
HISTBASEDIR=/var/log/bashhist # are we an interactive shell? if [ "$PS1" ] && [ -d $HISTBASEDIR ]; then REALNAME=`who am i | awk '{ print $1 }'` EFFNAME=`id -un` mkdir -m 700 $HISTBASEDIR/$EFFNAME >/dev/null 2>&1 shopt -s histappend shopt -s lithist shopt -s cmdhist unset HISTCONTROL && export HISTCONTROL unset HISTIGNORE && export HISTIGNORE export HISTSIZE=10000 export HISTTIMEFORMAT="%F %T " export HISTFILE=$HISTBASEDIR/$EFFNAME/history-$REALNAME case $TERM in xterm*) PROMPT_COMMAND='history -a && printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"' ;; screen) PROMPT_COMMAND='history -a && printf "\033]0;%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"' ;; *) PROMPT_COMMAND='history -a' ;; esac # Turn on checkwinsize shopt -s checkwinsize PS1="[\u@\h \W]\\$ " fi
This will configure bash to do several things:
- Store history files in /var/log/bashhist/<effective-username>/history-<actual-username>
- Add timestamps to history files
- Persist the history file to disk more frequently
The difference here between “effective” and “actual” plays a part when using su or sudo to run a shell as another user. When you enable these settings for root, and then do a sudo su –, the history file for root while you are su’ed will be stored in /var/log/bashhist/root/history-duane — or whatever your username is.
To fully enable this, we need to do a few more things. First, we need to make the /var/log/bashhist directory with (hopefully) appropriate permissions. The top-level directory needs to be 777 permissions in order to allow the shell snippet to make directories for new users as needed. Like with /tmp, the sticky-bit should prevent wild deletion by other users.
sudo mkdir -m 1777 /var/log/bashhist
We need to enable users-of-interest to source this snippet of shell into their .profile scripts. Add to the necessary .profile scripts:
source /usr/local/bin/bash-history.sh
Then we need to configure Splunk to read the history files with the right settings for timestamps. In props.conf:
[bash_history] TIME_PREFIX = ^# TIME_FORMAT = %s EXTRACT-userids = ^/var/log/bashhist/(?<effective_user>[^/]+)/history-(?<real_user>.*)$ in source
And in inputs.conf:
[monitor:///var/log/bashhist] disabled=false sourcetype=bash_history
If you’ve done all of this right, when you run the history command in bash you should see dates and times next to them, and bash histories should be searchable in Splunk.
Caveats
I mentioned caveats. There are a few – and I’m probably leaving some out.
Shell history is not an accurate source of audit-quality proof of things that were done / not done on a system. Nothing keeps a user from editing their history file after the fact. Splunk does pick up changes to the history file quickly and forwards them off-host. This may be a mitigating factor toward users editing the file to try to hide history, but a clever person would be able to evade. It is a good way to help keep honest people honest, but it’s not a strong control against an attacker or a dishonest person.
Also, shell history is written after a command finishes. If a user run a long-running command, like an ssh to a remote host, it won’t show up in the history until the task exits.
So, while it’s imperfect, this technique might be useful to you in keeping track of things happening on your Unix systems. Suggestions and improvements welcome.