Obfuscating Passwords in Shell Scripts
At the risk of repeating myself, I must say that this article is about obfuscating passwords – rendering obscure, unclear, or unintelligible – not hiding them. This can still be useful.
Imagine this scenario: you have a script that runs ldapsearch
on a username of your choice. The script requires a password for the service account used to connect to LDAP. You want some user to be able to run the script, but you don’t want to send the service account password to that user or to the root
.
Here’s what you can do. Store the service account password in an encrypted file. Give the user the password to decrypt the file. But make that file readable only by the root
account. How’s this possible? With sudo
. Here’s a more specific example:
#!/bin/bash username="" if [ -z "${username}" ]; then exit 1; fi readpass() { echo -n "Password: "; read -s p if [ -z "${p}" ]; then exit 1; fi } configure() { ldap_uri="ldaps://ldaps.domain.com" ldap_b="dc=domain,dc=com" ldap_d="cn=ServiceAccount,ou=Service Accounts" ldap_f="/etc/ad_query.conf.gpg" ldap_w="$(gpg --batch --decrypt --passphrase "${p}" -z 2 ${ldap_f} 2>/dev/null)" } ldap_lookup() { /usr/bin/ldapsearch -xLLL -b "${ldap_b}" -H "${ldap_uri}" -D "${ldap_d},${ldap_b}" \ -w "${ldap_w}" "(&(objectClass=user)(sAMAccountName=${username}))" | perl -p00e 's/\r?\n //g' } readpass; configure; ldap_lookup
Let’s put this script in /sbin/whois-ldap
. Let’s also chown root:root /sbin/whois-ldap; chmod 700 /sbin/whois-ldap
.
Now let’s create /etc/ad_query.conf
containing the password for the LDAP ServiceAccount
and f=/etc/ad_query.conf; chown root:root $f; chmod 400 $f
.
The final steps are to encrypt that file with a gpg
passphrase and to delete the plain-text original. You may want to skip the --passphrase
option and be prompted instead to avoid the passphrase ending up in your shell history and on whatever rsyslog
server that’s eavesdropping on you: gpg --batch --symmetric --passphrase "YourPGPPassphrase" $f; /bin/rm -f $f
So, I lied, the last step is to edit /etc/sudoers
and add something like this: igor ALL=(ALL) NOPASSWD: /sbin/whois-ldap
What did all of this accomplish? We have a script that requires a password for the domain account that transcends local root
. Now only user igor
who has the encryption passphrase can use this script.
At the same time igor
can’t do anything else root
can. For example, igor
can’t just run gpg
from command line to decrypt /etc/ad_query.conf
because that file is only readable by root
. And, while root
can read that file, the data in it is still encrypted.
So why is this obfuscation and not real security? Well, root
has access to /etc/ad_query.conf
, which is, although encrypted, is still readable and can potentially be cracked. A far easier approach for root
would be to put a wrapper over the pgp
command to act as a keylogger and steal the passphrase.