Go Ahead and Write Down Your Passwords

Tuesday, August 07, 2012

Boris Sverdlik


Another day, another password hack and yet another reason not to reuse passwords... 

Here is a simple bash script to generate strong passwords.

1) Install TrueCrypt http://www.truecrypt.org/

2) Create a hidden volume. Pick a strong passphrase you will not write down and use a keyfile

3) Mount the volume

4) Run the Script

I'll port it to Python this weekend, or maybe even something more platform independent. Also, don't forget to set Auto Dismount to 15 minutes, so you don't leave it up and running.


# For Resiliency I keep the volume in multiple places, but for ease of use
# of use, I suggest keeping it on Dropbox. Set TrueCrypt to unmount after
# 30 minutes of idle.

echo "Hello, "$USER". This will generate your password. Please make sure you have mounted your TrueCrypt volume with your password file"

echo -n "Please enter the path to your encrypted vault file [ENTER]: "
read vaultfile

echo -n "Please enter the patch to your encrypted mount, this will be used for temp files [ENTER]: "
read encmounts

echo -n "Enter the website or application that this password is for and press [ENTER]: "
read site

grep -i $site $vaultfile

if [ $? == 0 ]; then

echo -n "Do you want to create a new password for this existing account? (yes or no): "
read update

if [ "$update" == "yes" ]; then

echo -n "Enter the user ID you will be using and press [ENTER]: "
read name

echo -n "Enter maximum password length characters can the password be [ENTER]: "
read counts
sed "/$site/d" $vaultfile > $encmounts/tmp ; mv $encmounts/tmp $vaultfile

curl -s http://www.bing.com/news?q=$color > $encmounts/temp

newpass=`md5 $encmounts/temp | awk '{print $4}' | openssl sha | cut -c 1-$counts|sed -e 's/[a-z]/A/' -e 's/[0-9]/#/'`
echo $name $newpass $site >> $vaultfile
# rm $encmounts/tmp
exit 1
elif [ "$update" == "no" ]; then

echo "Goodbye"

echo -n "Enter the user ID you will be using and press [ENTER]: "
read name

echo -n "Enter maximum password length characters can the password be [ENTER]: "
read counts

curl -s http://www.bing.com/news?q=$color > $encmounts/tmp

newpass=`md5 $encmounts/tmp | awk '{print $4}' | openssl sha | cut -c 1-$counts |sed -e 's/[a-z]/A/' -e 's/[0-9]/#/'`
echo $name $newpass $site >> $vaultfile

rm $encmounts/tmp

echo "Goodbye"


Possibly Related Articles:
Network Access Control
Information Security
Passwords Authentication Access Control Script TrueCrypt Tutorial Passphrases
Post Rating I Like this!
Jakob Lell I've taken a quick look at your code and I've found some serious flaws:

1. The command "echo something|openssl sha" gives the output "(stdin)= 528167eed45c3a5a66dfaa5702e059d18a969b02". The cut command will then take the first $count characters from it and so it will get something starting with "(stdin)= ", which is totally predictable. Depending on the choosen password length there may be insufficient randomness because the first 9 characters are totally predictable.

2. The next problem is that the only source of randomness is the bing search (with the uninitialized variable $color as search term). The javascript of the bing site does contain some random-looking constants, which differ between multiple queries. However, I wouldn't trust it to be a cryptographically secure source of randomness just because it isn't designed to be secure. And even if this constants are actually generated in an unpredictable way at the moment, Microsoft may still remove this in the next site redesign or employ a cache for frequent searches.

3. The bing search which provides the randomness is queried via an unencrypted http connection so an attacker may be able to sniff the source of randomness used for the password generation and thus calculate the generated passwords.

4. The generated passwords only contain 4 bits of entropy per digit because they are generated from a hexadecimal hash. Replacing the first letter with an "A" and the first digit with a "#" may help to fulfil some password policies but it even further reduces the entropy and doesn't improve the security of the generated passwords in any way.
Andrew Newey Sounds like a lot of effot mate, but each to their own.
Boris Sverdlik @jakob while I agree that the replacement is weak, I actually have a for loop (which I didn't include) that randomizes the caps and special characters...

How do you figure the first 9 characters are predictable? You grab the search then run 2 hash functions against it. Totally unique...

You could go SSL, but then the attacker would still need to know what hash functions you are using, so again invalid point. You can replace the bing search with whatever.. The Twitter API is a good option, but I didn't want to include my OATH token in the code. :)
Jakob Lell The problem with the first 9 characters is that the command "openssl sha" outputs the filename before the actual hash. When hashing standard input, the output starts with "(stdin)= " and your code doesn't remove this static information. Just try out the following command in a shell:

counts=10;echo abc |openssl sha | cut -c 1-$counts|sed -e 's/[a-z]/A/' -e 's/[0-9]/#/'

This will generate the password "(Atdin)= #". The "s" from "stdin" has ben replaced by an "A" and the first digit of the actual hash has been replaced by "#".

I'd also strongly recommend to use a local source of randomness such as /dev/urandom. This is typically quiet secure and it can't be sniffed on the network. You can of course combine multiple sources of randomness by hashing them together.

The security also shouldn't depend on the attacker not knowing the code. You've published the code and so it's not hard to guess which hash algorithms you are using. Normal users aren't able to program their own password manager so they have to use an existing one, which can be analyzed by an attacker as well.
Boris Sverdlik Sorry... I'm lost as to what you are trying to say..

First your password file is encrypted, second the whole point of this stupid script is so users can use different passwords for different sites and not worry about remembering them.

Now, I'm still lost as to what you are trying to say about (stdin) considering no where in the code is it used to calculate the password outside of $color variable.

Yes echo filename would be the same, but i'm not echoing the filename..

look closer at what it does

1) pulls the contents out to a tmp file
2) runs an MD5 against that tmp file then
3) runs SHA against the output of the MD5 resultant set

bob$ curl -s http://www.bing.com/news?q=green > tp1
bob$ md5 tp1 | awk '{print $4}' | openssl sha | cut -c 1-15

bob$ curl -s http://www.bing.com/news?q=purple > tp1
bob$ md5 tp1 | awk '{print $4}' | openssl sha | cut -c 1-15
Jakob Lell That's actually quiet strange. My version of openssl behaves differently and outputs the string "(stdin)= " before the actual hash. I'm using openssl version 1.0.1-4ubuntu5.3 as shipped with Ubuntu 12.04 amd64.

$ echo abc|openssl sha
(stdin)= 4cf315510f27558eb84011bb47333b4a5ae10a48
$ echo abc| openssl sha | cut -c 1-15
(stdin)= 4cf315
Boris Sverdlik No it's not strange... You're missing the first piece of the code... I'm not echoing out the file name..

I'm running an md5 against it, then the 2nd (awk) command rips out "MD5 (tp1) =" from the results, then it's run through the sha function

newpass=`md5 $encmounts/tmp | awk '{print $4}' | openssl sha |
Jakob Lell On my system the command "openssl sha" outputs "(stdin)= ..." regardless of the input it gets via stdin and this static string is not removed by your code. So it's not important whether you pass it a static string or an md5 hash. Which operating system and which version of openssl are you using? According to your example above your version of openssl only outputs plain hash without the string "(stdin)= " in the beginning.
Boris Sverdlik I'm guessing you failed to notice that md5 isn't a valid command on your system either... The original code was on OS X, but if you knew what you were doing you would of probably mentioned in your first post that

md5 isn't working for you

bob@dontclickshit:~$ uname -ori x86_64 GNU/Linux

bob@dontclickshit:~$ md5
-bash: md5: command not found

and that the output of md5sum (the *nix) command formats differently than osx

bob@dontclickshit:~$ md5sum tp1
0d24e4a2296d18d7b9ad856245b9d1fe tp1

so Yes... on your box because you clearly don't understand what the code was doing it would show up as

bob@dontclickshit:~$ curl -s http://www.bing.com/news?q=green > tp1
bob@dontclickshitmd5sum tp1 | awk '{print $4}' | openssl sha | cut -c 1-15

bob@dontclickshit:~$ curl -s http://www.bing.com/news?q=purple > tp1
bob@dontclickshit:~$ md5sum tp1 | awk '{print $4}' | openssl sha | cut -c 1-15

but since I have what clearly seems to be more experience than you, let me show you how it works on your machine..

I replaced md5 with md5sum and wait for it, awk '{print $1}' because only the 1st column is the hash value of the md5 function.

bob@dontclickshit:~$ uname -ori x86_64 GNU/Linux
bob@dontclickshit:~$ curl -s

http://www.bing.com/news?q=green > tp1
bob@dontclickshit:~$ md5sum tp1 | awk '{print $1}' | openssl sha

bob@dontclickshit:~$ curl -s http://www.bing.com/news?q=purple > tp1
bob@dontclickshit:~$ md5sum tp1 | awk '{print $1}' | openssl sha
Boris Sverdlik Are those random enough for you? It's not openssl sha that's broken, it's the fact that A) it did not go through an MD5 function and B) it did not parse it correctly because of the version differences.
Jakob Lell I did notice that md5 isn't available on my system but this isn't relevant for my point because at least some versions of openssl output the string "(stdin)= " before the actual hash when running "openssl sha". If the openssl command does this then the first 9 digits of the generated password are constant and don't depend on whether the md5 command works or not. Even if your system is not affected, this may lead to predictable passwords on other systems. I've repeated your commands on my system (Ubuntu 12.04 amd64) and here are the results:

$ uname -ori
3.2.0-27-generic x86_64 GNU/Linux
$ curl -s http://www.bing.com/news?q=green > tp1
$ md5sum tp1 | awk '{print $1}' | openssl sha
(stdin)= 40eaf1ca40c875214a10f98317103b5792be2187
$ curl -s http://www.bing.com/news?q=purple > tp1
$ md5sum tp1 | awk '{print $1}' | openssl sha
(stdin)= b3e2a8581c31bf628613e245eaae68f5b8b8d802

And the same on an Ubuntu 10.04 vm with openssl 0.9.8k-7ubuntu8.13:
$ uname -ori
2.6.32-41-generic unknown GNU/Linux
$ curl -s http://www.bing.com/news?q=green > tp1
$ md5sum tp1 | awk '{print $1}' | openssl sha
$ curl -s http://www.bing.com/news?q=purple > tp1
$ md5sum tp1 | awk '{print $1}' | openssl sha

As you can see the output of "openssl sha" depends on the version of openssl and you'd better add support for both version so that your code doesn't break when upgrading openssl.

By the way the openssl command also provides an option to generate cryptographically secure random numbers:
$ openssl rand -hex 10

That's definitely better than using hash values of a dynamically generated website (which may become predictable due to a site redesign, caching or temporary network/server errors).
Boris Sverdlik I give up.. you're obviously smarter than me... If you think i'd be happy with an 8 character password of "(stdin)=" for each account as in your version, and would publish a script to that effect, than you must be a rocket scientist.

You can clearly see that I did get rid of the garbage in the MD5 sum, why would I leave in the SHA?

echo "(stdin)=
40eaf1ca40c875214a10f98317103b5792be2187" | cut -c 1-8

You clearly however didn't notice that MD5 wasn't working, just pointing to your theory "Hey I'm so frigging smart"... Yes.. "My system" will give you the same hash value for two totally random values in your bizarre little world... Where I'm hashing the same damn error "-bash md:command not found"

Here watch... Still paying attention Mr Wizard?

bob@dontclickshit:~$ md5 stupid |openssl sha
-bash: md5: command not found

bob@dontclickshit:~$ md5 dumb |openssl sha
-bash: md5: command not found

and just because I think I'm smarter than the average bear (not really, just definitely brighter than you) I updated to the latest stable release http://www.openssl.org/source/

bob@dontclickshit:~$ openssl version
OpenSSL 0.9.8o 01 Jun 2010

bob@dontclickshit:~$ md5 dumb |openssl sha
-bash: md5: command not found

bob@dontclickshit:~$ md5sum dumb |openssl sha

Please tell me you're done at this point?
Jakob Lell You've told that you've downloaded the "latest version" but then you show version 0.9.8o. However the latest stable version of openssl is actually 1.0.1c. If you had tried this version, you would have seen that this version does output the string "(stdin)= " before the actual hash. Since older versions of openssl just output the hash, your code works fine on your system. However, you should acknowledge that the behavior of openssl has changed and the program will generate weak passwords when using a more recent version of openssl.

I didn't mention the missing md5 program in my previous posts because this doesn't influence the output format of openssl and it was obvious from the code that you would just pass the md5 hash to openssl. Actually using a chain of two different hash algorithms is quiet useless and doesn't improve the security (unless you chain a lot more hash functions and keep the ordering of the hash functions a secret).
Matthew Harvey I don't really understand the point of this debate. As I take it, the script presented was intended to illustrate a point, which is that it's not that hard to use simple tools available on the system to create highly randomized passwords and to store them in a highly secure, and yet easily accessible, manner. It's just proof-of-concept code, not a ready-for-release open source tool or something.
The views expressed in this post are the opinions of the Infosec Island member that posted this content. Infosec Island is not responsible for the content or messaging of this post.

Unauthorized reproduction of this article (in part or in whole) is prohibited without the express written permission of Infosec Island and the Infosec Island member that posted this content--this includes using our RSS feed for any purpose other than personal use.