3

I sometimes mistakenly type my su password in a linux terminal that is echoing the typed characters. It gets recorded in ~/.bash_history which makes me feel insecure. Does anyone have a short script (bash one-liner?) to clean .bash_history of any plain text passwords?

Using sed leaves it's own traces in the .bash_history file, but if readline and/or history service could be temporarily disabled this might work:

sed -ir -e 's/su_password/PASSWORD_REMOVED/g' ~/.bash_history

And this could create additional problems/holes if the password is often used as part of other phrases/words.

Ideally, the script should just peruse the hashed passwd list (/etc/shadow) to create a list of search terms. Then it would have to hash portions of the file it's checking (.bash_history) for comparison. The problem is knowing how much of the text in the file to hash during the comparison as the length of the password is unknown. Alternatively, it could request the password in a secure way, like passwd does, before doing the grep/sed.

hobs
  • 18,473
  • 10
  • 83
  • 106
  • 5
    If you start a command with a space, it won't be recorded. That might help with the sed command. – Kerrek SB Aug 25 '11 at 00:20
  • 1
    This doesn't answer your question, but from time to time if I'm typing quickly and miss a password prompt, resulting in a password going in as a bash command, I end my session with `kill -9 $$`, which terminates the login session without executing logout functions. No history is written for the session. – Michael Berkowski Aug 25 '11 at 01:08
  • @Kerrek SB: Commands started with space will be recorded unless `HISTCONTROL=ignorespace` is set. You should definitely be checking this variable before relying on the behavior. – sorpigal Aug 25 '11 at 12:01
  • @Sorpigal: Very good point, thanks! – Kerrek SB Aug 25 '11 at 12:05
  • 1
    @Sorpigal, thanks. I guess the answer is to check HISTCONTROL (or unset HISTFILE), do a sed (but with a bit more restrictive pattern matching around the password), then set HISTCONTROL and/or HISTFILE back the way they were. – hobs Aug 25 '11 at 13:23
  • @Kerrek SB, unfortunately I have a customized prompt that does my history recording to comment commands with datetime, sequence #, and pwd, and append a ".bash_history_forever" file. – hobs Aug 25 '11 at 13:26
  • @Michael, thanks for the tip. Doesn't quite solve all my issues, but definitely a good trick. – hobs Aug 25 '11 at 13:27
  • Here's how I do history syncing between terminals, plus archiving. It makes password cleanup a bit tricky. In ~/.bashrc or /etc/bash.bashrc I have `export PROMPT_COMMAND="history -a; history -c; history -r; history 1 >> ~/.bash_history_forever; $PROMPT_COMMAND"` – hobs Aug 27 '11 at 08:55

4 Answers4

2

Not exactly just a one-liner, instead, a function:

eh () { history -a ; vi + ~/.bash_history ; history -r ; }

add this line to your .bashrc or .bash_profile. When run it

  1. saves the buffer to your .bash_history
  2. opens up .bash_history in vi, except with the pointer at the bottom of the file.
  3. restores the edited file to your current history buffer

While in vi, you can go up and down with the arrow keys, remove a line with dd and close and write the file with [Esc] :wq

now you just need to type eh at the command line and edit your history

eh stands for "edit history"

user886694
  • 55
  • 7
0
$ echo -n password=; stty -echo; sed -i "s/$(head -1)/PASSWORD_REMOVED/g" ~/.bash_history; stty echo
top-secret password that never appears anywhere else to make it easy to guess
$ #you have to type it in and press enter

The echo gives you the prompt. The stty helps protect against people looking over your shoulder. Make sure you escape anything (i.e. backslashes).

yingted
  • 9,996
  • 4
  • 23
  • 15
0

I usually do a echo > .bash_history to clear this. Although your password can show up in strange places so you might want to do a sudo grep "password" -R / first, to see if its anywhere else on the system, and then clear out your history.

rook
  • 66,304
  • 38
  • 162
  • 239
  • Yea, but I don't wan to delete ALL of the history file. I'd like to keep all but just the plain-text passwords. Good idea on the grep command, though. – hobs Aug 25 '11 at 13:18
0

Since there weren't any answers that did the trick for me, I thought I'd share the script I'm currently using. It's certainly not a one-liner and not even bash ... but it works.

#!/usr/bin/env python
import os
user=os.getenv('USER')
if not user:
    user='hobs'
home=os.getenv('HOME')
if not home:
  home=os.path.normpath(os.path.join(os.path.sep+'home',user))
histfile=os.getenv('HISTFILE')
if not histfile:
    histfile=os.path.join(home,'.bash_history')
from optparse import OptionParser
p = OptionParser(usage="%prog [options] password", add_help_option=True)
p.add_option('-p', '--password', '--pass', '--pw', dest='pw',
             default =None,
             help="The plaintext password string you'd like to find and replace throughout your bash history file(s)", )
p.add_option('-r', '--replacement-password', '--replacement', '--filler', '--substitution', dest='rep',
             default ='',
             help="The replacement string, passphrase identifier, tag, or filler you'd like to leave behind wherever the password was found and removed.", )
p.add_option('-f', '--bash_history', '--historyfile', '--file', '--path', '--filename', dest='hfile',
             default =histfile,
             help="The text file where your password may have been accidentally recorded and where you'd like it removed. Default = ~/.bash_history.", )
(o, a) = p.parse_args()
if a and not o.pw:
    o.pw=' '.join(a) # password can have spaces in it
    print o.pw
    print len(o.pw)
# TODO: Check if the history buffer will record the invocation of this script that includes a plaintext password
#       Alternatively, launch the search/replace task in the background to start
#       after history has had a chance to record the last command in the history buffer
if o.pw:
    import warnings
    warnings.warn("Make sure you invoked "+p.get_prog_name()+" in such a way that history won't record this command (with a plaintext password) in the history file. It would be much  better if you didn't supply the password on the command line and instead allowed this script to securely prompt you for it.",RuntimeWarning)
if not o.pw:
    import getpass
    o.pw=getpass.getpass()
if len(o.pw)<4:
    raise ValueError(p.get_prog_name() + " doesn't accept passwords shorter than 4 characters long to prevent accidental corruption of files by purging common character combinations. The password you supplied is only "+str(len(o.pw))+" characters long.")
import fileinput
for line in fileinput.FileInput(o.hfile,inplace=1):
    line = line.replace(o.pw,o.rep)
    print line,
hobs
  • 18,473
  • 10
  • 83
  • 106