Bash Tips: Passing Passwords
By
Bash offers any number of simplifications, especially when it comes to pesky individual steps in installation routines for larger software packages. Some caution is advisable, though, if you need to handle database and application passwords, which can easily be compromised.
From the administrator’s point of view, installing web applications always follows the same pattern: download and unpack the package, prepare the database, then introduce the two components to one another, typically in the form of a configuration file. To discover what entries you need – in what syntax and in which file – you traditionally read the README, but the installation can be faster for an administrator (and often less prone to error) if the developers include a shell script that takes the administrator by the hand and guides them through the settings.
This is the approach that the community surrounding Magento, a popular eCommence platform for PHP, takes. The website provides an installer in the form of a Bash script. The script (see an excerpt in Listing 1) follows a simple pattern; it queries whether the required MySQL database exists, asks for various connection information for the database, then downloads the required packages with wget. It then sets up a couple of permissions and feeds a schema to the database so you can launch the web application.
Listing 1: Magento Installer
01 #!/bin/bash 02 03 clear 04 05 echo "To install Magento, you will need a blank database ready with a user assigned to it." 06 07 echo -n "Database Host (usually localhost): " 08 read dbhost 09 10 echo -n "Database Name: " 11 read dbname 12 13 echo -n "Database User: " 14 read dbuser 15 16 echo -n "Database Password: " 17 read dbpass 18 19 echo -n "Store URL: " 20 read url 21 22 echo -n "Admin Username: " 23 read adminuser 24 25 echo -n "Admin Password: " 26 read adminpass 27 [...] 28 echo "Downloading and extracting packages ..." 29 30 wget http://www.magentocommerce.com/downloads/assets/1.4.1.1/magento-1.4.1.1.tar.gz 31 wget http://www.magentocommerce.com/downloads/assets/1.2.0/magento-sample-data-1.2.0.tar.gz 32 tar -zxvf magento-1.4.1.1.tar.gz 33 tar -zxvf magento-sample-data-1.2.0.tar.gz 34 [...] 35 echo "Importing sample products ..." 36 mysql -h $dbhost -u $dbuser -p$dbpass $dbname < data.sql 37 [...] 38 echo "Installing Magento ..." 39 40 php-cli -f install.php -- \ 41 --license_agreement_accepted "yes" \ 42 --db_host "$dbhost" \ 43 --db_name "$dbname" \ 44 --db_user "$dbuser" \ 45 --db_pass "$dbpass" \ 46 [...] 47 echo "Finished installing Magento"
Visible Secrets
Security-conscious administrators will have noticed a couple of details. In line 16, the script uses echo -n "password: **" to create a prompt that doesn’t cause a line break. The -n option keeps the cursor to the right of the output. The script then prompts for the database password. Some lines farther down, this pattern is repeated for the administrator account.
If you work in an open plan office or suspect that somebody is shoulder surfing, you will not be very happy to see the password entry echoed onto the screen. The Bash read command normally repeats all of your input on the standard output.
At this point, it could be useful to think about how these characters actually get where they are. If a user is sitting directly in front of the computer, the physical keyboard passes the key presses to the kernel. The kernel passes them to an X server, assuming an X11 interface is running, and the X server converts them into X events and sends them to the correct window; this will be a terminal emulation such as xterm or konsole.
Inside the terminal program you will typically have a shell like Bash running. The two programs are connected by a pipe that presents a pseudo-terminal device such as /dev/pts/0 on the terminal side and the standard input on the shell side. If a Bash user needs a file for this, they can use /proc/self/fd/0. Two other pipes, numbered 1 and 2, combine the two sides for the standard output and the standard error output in the same way (see Figure 1).
The terminal program is also responsible for showing the keys you press in the terminal, not in the shell. To try this out, you can issue the command
stty -echo
in the shell. The command then uses ioctl() to send a change to the terminal driver, which will not display any keys you press from now on. However, the shell will continue to process commands and create the normal output. To restore the normal state, you just need to enter the complementary command:
stty echo
Curious Eyes
This means you can disable the echo in shell scripts and then reenable it after entering the password. To avoid the need to use this external command, Bash also has a built-in function that works in a similar way. The -s option in read also tells the shell to suppress the echo.
Bash has another couple of useful options here: for example, the -n <number> key defines the number of characters that read should read. You don’t even need a newline for this, which the shell always otherwise requires to terminate input. If you use a combination of read -n1 x, Bash will wait for a single key press and store this in the variable x.
Sometimes – in wild arcade shooters, for example – programmers only want to wait a limited time for input. The option for handling this is -t <seconds>. After the specified time, Bash processes the subsequent command. Then you need to check the exit status of the command with $? to discover whether or not you have any input. Listing 2 implements proof of concept in the form of a small race into space in retro design. The user can guide a small spaceship through an asteroid belt using the G and H keys, leaving a tail of exhaust gas in its wake.
Listing 2: Space Race in Bash
01 #!/bin/bash 02 03 pos=40 04 width=80 05 06 while true; do 07 read -t1 -s -n1 x 08 case "$x" in 09 g) pos=$(($pos - 1)) ;; 10 h) pos=$(($pos + 1)) ;; 11 esac 12 for ((i=0; i < $width; i++)) 13 do 14 if [ $i -eq $pos ]; then 15 echo -n 'V' 16 elif [ $(($RANDOM % 9)) -eq 0 ]; then 17 echo -n '*' 18 else 19 echo -n ' ' 20 fi 21 done 22 echo 23 done
The Magento installer, now improved by adding read -s, has another problem. In line 36 of Listing 1, the script calls MySQL to initialize the database and uses the -p$dbpass option to pass the password it queried previously into the database. Other users logged in to the same computer at run time can see these details in the clear in the process list by typing ps auxwww.
This explains why passwords should be banned from command-line arguments. An alternative when handing over data would be to use environmental variables, but you can access these in the same way with ps aueww. Absurdly, many programs implement this insecure method of launching MySQL via the MYSQL_PWD environmental variable. The best way to transfer a cleartext password will thus be in the configuration files, which the software reads, or, alternatively, with the use of pipes, such as standard input. Purists would comment that unencrypted passwords should never be stored in the clear and point instead to hashes or tokens, in the style of Kerberos. However, you might find it difficult to implement this with Bash alone.
Issue 269/2023
Buy this issue as a PDF
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Find SysAdmin Jobs
News
-
MNT Seeks Financial Backing for New Seven-Inch Linux Laptop
MNT Pocket Reform is a tiny laptop that is modular, upgradable, recyclable, reusable, and ships with Debian Linux.
-
Ubuntu Flatpak Remix Adds Flatpak Support Preinstalled
If you're looking for a version of Ubuntu that includes Flatpak support out of the box, there's one clear option.
-
Gnome 44 Release Candidate Now Available
The Gnome 44 release candidate has officially arrived and adds a few changes into the mix.
-
Flathub Vying to Become the Standard Linux App Store
If the Flathub team has any say in the matter, their product will become the default tool for installing Linux apps in 2023.
-
Debian 12 to Ship with KDE Plasma 5.27
The Debian development team has shifted to the latest version of KDE for their testing branch.
-
Planet Computers Launches ARM-based Linux Desktop PCs
The firm that originally released a line of mobile keyboards has taken a different direction and has developed a new line of out-of-the-box mini Linux desktop computers.
-
Ubuntu No Longer Shipping with Flatpak
In a move that probably won’t come as a shock to many, Ubuntu and all of its official spins will no longer ship with Flatpak installed.
-
openSUSE Leap 15.5 Beta Now Available
The final version of the Leap 15 series of openSUSE is available for beta testing and offers only new software versions.
-
Linux Kernel 6.2 Released with New Hardware Support
Find out what's new in the most recent release from Linus Torvalds and the Linux kernel team.
-
Kubuntu Focus Team Releases New Mini Desktop
The team behind Kubuntu Focus has released a new NX GEN 2 mini desktop PC powered by Linux.