Problem You need to run a command, but you want some assurance that it's the command you thought it was. Requirements Cooking with this recipe requires WebJob 1.3.0 or higher. If you do not have that, refer to the instructions provided in the README.INSTALL file that comes with the source distribution. The latest source distribution is available here: http://sourceforge.net/project/showfiles.php?group_id=40788 Each system must be running UNIX and have at least the following utilities: basename, egrep, expr, tr, and webjob. The commands presented throughout this recipe were designed to be executed within a Bourne shell (i.e. sh or bash). Solution The solution is to compute a cryptographic hash or message digest of the command you intend to run and compare it to a predetermined value. If the digests match, then the command you intend to run is probably the one that will be executed. There are, however, several attack vectors that you must consider: - The command could be altered between the time it was hashed and the time it was executed. - The command could be altered during execution. - The command could be hijacked prior to or upon execution. - The command's output could be hijacked during execution. - The computed hash could be a lie. The hashrun script (see Appendix 1) implements this solution. The command provided below will extract that script from this recipe. $ sed -e '1,/^--- hashrun ---$/d; /^--- hashrun ---$/,$d' webjob-hashrun.txt > hashrun Here is the script's usage: Usage: hashrun [-H webjob-home] [-t type] -h hash -- command [options] The arguments for hashrun have the following meanings: command [options] The fully qualified path of the target command along with any optional options. hash A hexadecimal representation of the command's expected hash. type The desired hash type (i.e. algorithm). Value must be one of {MD5|SHA1}. The default value is MD5. webjob-home The prefix where webjob was installed. The default value is /usr/local/integrity. Assuming that ps is located in /bin, its expected MD5 hash is 61a8ae3c27ef04021d7b508f397210e4, and the webjob installation prefix was /usr/local/integrity, then hashrun would be invoked as follows: $ hashrun -h 61a8ae3c27ef04021d7b508f397210e4 -- /bin/ps -aux Closing Remarks Using hashrun within a WebJob client-server framework allows you to run commands that reside on a given client while maintaining hashes of those commands on the server. Credit This recipe is brought to you by Klayton Monroe, August 2003. Appendix 1 --- hashrun --- #!/bin/sh IFS=' ' PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin PROGRAM=`basename $0` Usage() { echo 1>&2 echo "Usage: ${PROGRAM} [-H webjob-home] [-t type] -h hash -- command [options]" 1>&2 echo 1>&2 exit 1 } while getopts "H:h:t:" OPTION ; do case "${OPTION}" in H) WEBJOB_HOME="${OPTARG}" ;; h) TARGET_HASH="`echo ${OPTARG} | tr "[:upper:]" "[:lower:]"`" ;; t) DIGEST_TYPE="${OPTARG}" ;; *) Usage ;; esac done shift `expr ${OPTIND} - 1` if [ -z "${TARGET_HASH}" -o -z "${COMMAND=$1}" ] ; then Usage fi shift PATH=${PATH}:${WEBJOB_HOME=/usr/local/integrity}/bin echo ${COMMAND} | egrep "^/" > /dev/null 2>&1 if [ $? -ne 0 ] ; then echo "${PROGRAM}: Command='${COMMAND}' Error='Command must be a fully qualified path.'" 1>&2 exit 2 fi if [ ! -x ${COMMAND} ] ; then echo "${PROGRAM}: Command='${COMMAND}' Error='Command must exist and be executable.'" 1>&2 exit 2 fi ACTUAL_HASH=`webjob -h -t ${DIGEST_TYPE=md5} ${COMMAND}` if [ "${ACTUAL_HASH}" != "${TARGET_HASH}" ] ; then echo "${PROGRAM}: Command='${COMMAND}' TargetHash='${TARGET_HASH}' ActualHash='${ACTUAL_HASH}' Error='Hash mismatch.'" 1>&2 exit 2 fi ${COMMAND} $* --- hashrun ---