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.
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Thousands of Linux Servers Infected with Stealth Malware Since 2021
Perfctl is capable of remaining undetected, which makes it dangerous and hard to mitigate.
-
Halcyon Creates Anti-Ransomware Protection for Linux
As more Linux systems are targeted by ransomware, Halcyon is stepping up its protection.
-
Valve and Arch Linux Announce Collaboration
Valve and Arch have come together for two projects that will have a serious impact on the Linux distribution.
-
Hacker Successfully Runs Linux on a CPU from the Early ‘70s
From the office of "Look what I can do," Dmitry Grinberg was able to get Linux running on a processor that was created in 1971.
-
OSI and LPI Form Strategic Alliance
With a goal of strengthening Linux and open source communities, this new alliance aims to nurture the growth of more highly skilled professionals.
-
Fedora 41 Beta Available with Some Interesting Additions
If you're a Fedora fan, you'll be excited to hear the beta version of the latest release is now available for testing and includes plenty of updates.
-
AlmaLinux Unveils New Hardware Certification Process
The AlmaLinux Hardware Certification Program run by the Certification Special Interest Group (SIG) aims to ensure seamless compatibility between AlmaLinux and a wide range of hardware configurations.
-
Wind River Introduces eLxr Pro Linux Solution
eLxr Pro offers an end-to-end Linux solution backed by expert commercial support.
-
Juno Tab 3 Launches with Ubuntu 24.04
Anyone looking for a full-blown Linux tablet need look no further. Juno has released the Tab 3.
-
New KDE Slimbook Plasma Available for Preorder
Powered by an AMD Ryzen CPU, the latest KDE Slimbook laptop is powerful enough for local AI tasks.