We've been through quite a lot in the shell scripting series so far. Combining all of the parts, let's now begin to talk about how to do shell script debugging as well as writing more secure shell scripts.
Debugging shell scripts
The art of figuring out when a shell script does something unexpected can be somewhat tricky. No debugger exists which can expose shell script problems. However, there are certain commands and tricks that can be used to get more information during execution.
Two options are set in bash with the use of the set command. In any shell script, as the second line, insert the following:
What does this do? Using the -x switch turns on the bash xtrace option. This option will print all commands after expansion, so that any variable substitution is shown during shell script execution. The second option, -v, prints commands verbatim before they are run. In a long shell script, it is often quite useful to see exactly what is happening.
One other quick addition, directly after adding the set -xv statement, enter the following:
This command places all output from the shell script in the user's console log. This could be useful if the shell script is run via a Remote or GUI process, such as Apple Remote Desktop, or with an Applescript wrapper. Note also that this command is unique to OS X.
Securing shell scripts
How can shell scripts be secured? It is generally somewhat difficult to secure shell scripts, as they are written in plain text, and a user with a certain amount of knowledge can exploit poorly written shell scripts. Below are some easy things that will make shell scripts less vulnerable.
1. Set the PATH variable.
A very common method of attack is exploiting a PATH variable to include directories where malicious programs may be installed. At the top of any shell script on OS X, setting the PATH to:
provides a modicum of security. Why? Usually these directories are only available to administrators or the root user, and can be trusted.
Note also, it is very dangerous to include the current working directory, signified by a dot, in the PATH variable. It is trivial to write a Trojan Horse that exploits the inclusion of the current directory in the PATH.
2. Reset the IFS variable.
Up to now, we've not talked about this environment variable. It is set each time a new shell is opened. In shell scripting, it is should be set in the following way at the beginning of a script:
Setting this variable prevents the same sort of attacks that are accomplished through the use of a malicious PATH variable.
3. Check error codes and use exit values.
When first writing shell scripts, it is tempting to omit the use of error codes and exit values. However, as scripts become more complex, checking for error codes and exit values can be become of great importance.
4. Validate input
Validating input is extremely important, as this type of bug is a source of many recent exploits. Verify that the type of input received is the type of input expected. If asking for an integer, verify that an integer has been entered.
Validation also minimizes the effect of malicious input as well. It also best to quote any input with double quotes. Quoting prevents the accidental execution in the shell script with input from the user.
5 . Don't make a script setuid or setgid
Unlike other Unices, OS X allows scripts to be setuid or setgid. Avoid this practice at all possible cost. If the shell script is vulnerable in any way, the entire operating system is at risk from a setuid setgid script.
Hopefully, these recommendations don't seem to onerous. With these things in mind, your shell scripts should be on their way to being more secure. Next time, we'll take a look at quoting practices in bash, one of the areas that causes problems to new shell script authors.