Grepping History

Datetime:2016-08-23 00:57:31          Topic: AWK           Share

In my estimation, the most useful Unix command will always and forever be grep , but history is also high on my list. Combined, the two form a dynamic duo that can be used to answer the question, “what did I come up with to solve x, y or z hacky problem from the command line?”

In the good old, bad old days, this was a sport among sysadmins — who could chain the most elaborate series of commands to produce the most improbable result, using the humble Unix shell?

Obfuscated Forkbomb

Here’s one of my favorites. I certainly don’t claim authorship of it, and if you know what’s good for you, don’t ever run this:

Seriously, don’t run this:

:(){ :|: & };:

The short answer is that the above command is the Unix emoticon for “your system is about to be very sad.”

Here’s a more readable version:

Seriously, don’t run this:

forkbomb()
{ 
    forkbomb | \
    forkbomb &
};
forkbomb

The hunt for my longest command

I wanted to figure out what my most elaborate command was on my desktop, so I looked at my tcsh history with hilarious results:

chris@girlfriend [4:15]:1:~% find .history -type f -exec cat {} \; | awk 'length > max_length { max_length = length; longest_line = $0 } END { print longest_line }'
cat: .history/root-girlfriend.local.140317164504: Permission denied
E?I&???#(eq??jUzlz?KJ?2}?u??Uf???9?s?]SU
      ?Ț????<J?V???%렱1P?V????$^?\HR????0]t
[... more binary data garbage]

This command pipes my shell history into a simple awk program that compares each line to the longest known line. It registers the value of the current longest line into a variable, which is then printed once all the lines in my history have been searched.

In this case, my tcsh history seems to contain some binary data. I’ll have to clean that up, first by running the find command as root and piping it into the Unix utility strings , which converts binary data to ASCII:

chris@girlfriend [4:19]:3:~% sudo find .history -type f -exec cat {} \; | awk 'length > max_length { max_length = length; longest_line = $0 } END { print longest_line }' | strings
Password:
#(eq
[ ...ASCII gibberish]

More gibberish! Clearly I had pasted some binary nonsense into the command line, and it was written into my tcsh command history.

Maybe I could exclude it? Let’s run strings before awk this time to weed out any multi-line binary gibberish.

chris@girlfriend [4:19]:4:~% sudo find .history -type f -exec cat {} \; | strings | awk 'length > max_length { max_length = length; longest_line = $0 } END { print longest_line }'
1111poooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooee aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Still pretty noisy. (This might be the work of my cat.) I bet if I limited the search to lines containing the pipe character | I’d come up with something more exciting.

chris@girlfriend [4:22]:5:~% sudo find .history -type f -exec cat {} \; | strings | grep '|' | awk 'length > max_length { max_length = length; longest_line = $0 } END { print longest_line }'
curl -H "Authorization: Token token=REDACTED,provider=REDACTED" https://vip1-us-east-1.REDACTED:443/users/recommended | grep -q null > /dev/null 2 > & 1

Great! A bunch of old auth tokens! ​ sigh . Well, this isn’t what I was hoping for, but it leads me to an important lesson about logging your history.

The downside of logging your history

At some point or another, you’re bound to type in something that you don’t want in the hands of a malicious stranger. Therefore the moral of this story is to:

  1. Yes, save your shell history indefinitely so you can go back to it when you want to remember how to do repetitive tasks that aren’t quite worthy of a full-blown shell script. This is how I set that up when I used to run Turbo Shell:

    set history=1000
    set savehist=(1000 merge)
    set histdir=~/.history/${USER}/${HOST}/`date +%Y/%m/%d`
    if ( ! -d ${histdir} ) then
      if ( -f ~/.history ) then
        mv ~/.history ~/.history-orig-`date +%Y%m%d`
      endif
      mkdir -p ${histdir}
    endif
    set histfile=${histdir}/`date +%H%M%S`
  2. Save your history to a file, but restrict who can read it (mode 0400 ). If you are particularly security-conscious, encrypt your history file.

  3. Scrub sensitive data from your history. There’s nothing more humbling than a good history | grep AWS_SECRET to spoil your day. Don’t forget to scrub your vim command history if you opened your history file up to do a bit of the old :%s/AWS_SECRET.*/nope/g . Open the history in an editor, turn off that editor’s command history, then search for known security tokens, like your password, your AWS_SECRET_KEY , your GitHub login tokens, or any PII you’d want to scrub.

  4. If you happen upon some other chap or lady’s shell history and notice an out of place string of characters, like, say, !!!j4bb3rw0cky_123456!!! , do be a mensch and let them know they accidentally pasted their password into their command prompt.





About List