AIX Shell Scripting Made Easy

http://www.ibmsystemsmag.com/aix/administrator/security/shell_easy/?page=1

AIX Shell Scripting Made Easy

September 2012 | by Andrew Wojnarek

In “AIX Shell Scripting Made Simple,” I explained the basics of shell scripting and why it’s so useful. However, it’s not only simple, but easy! Delving further, we’ll see how easy and powerful this tool can be. Additionally, we’ll explore building more advanced borne shell scripts as well as perl “one-liners” for certain situations.

As you may know, IBM releases security vulnerability information for AIX. The site usually gives a description of the vulnerability, fileset levels it effects and where to find the PTF/EFIX. So the script, if built right, will go out to all your servers and detect whether they’re vulnerable.

The Shell Script

The mockup script shown here assumes you have keys set up to SSH out to each server. It does not have to be run as root. The entire shell script, without comments, can be found here.

#!/usr/bin/env sh
# Checks for vulnerability in AIX RPC first issued May 8th.     

#############
# Variables #
#############
# These are all the levels vulnerable to this exploit.
_vulnerable_levels=(  "5.3.12.0" "5.3.12.1" "5.3.12.2" "5.3.12.3"
 "5.3.12.4" "5.3.12.5" "6.1.5.0" "6.1.5.1" "6.1.5.2"
 "6.1.5.3" "6.1.5.4" "6.1.5.5" "6.1.5.6" "6.1.5.7"
 "6.1.6.0" "6.1.6.1" "6.1.6.2" "6.1.6.3" "6.1.6.4"
 "6.1.6.5" "6.1.6.6" "6.1.6.7" "6.1.6.8" "6.1.6.9"
 "6.1.6.10" "6.1.6.11" "6.1.6.12" "6.1.6.13" "6.1.6.14"
 "6.1.6.15" "6.1.6.16"  "6.1.7.0" "6.1.7.1" "7.1.0.0"
  "7.1.0.1"  "7.1.0.2"  "7.1.0.3"  "7.1.0.4"  "7.1.0.5"
  "7.1.0.6"  "7.1.0.7"  "7.1.0.8"  "7.1.0.9"  "7.1.0.10"
  "7.1.0.11"  "7.1.0.12"  "7.1.0.13"  "7.1.0.14"  "7.1.0.15"
  "7.1.0.16" "7.1.0.17" "7.1.1.0" "7.1.1.1" )

This produces an array with the filesets affected by this vulnerability, which is important because we need to define all of the vulnerable filesets. You can find these values on the site where the vulnerability is defined.

_ssh_opts='-q -o BatchMode=yes -o ConnectTimeout=20
 -o ConnectionAttempts=1 -o ClearAllForwardings=yes'

This indicates the options we’re going to use to SSH to each servers. You can change these without affecting the script output.

# Makes text bold.
_b=`tput smso`

# Unset text bold.
_nb=`tput sgr0`

_date=`date +"%m%d%y_%H%M%S"`

_hosts="host1 host2 host3"

This variable specifies which servers you want to use. If you don’t set it, it won’t work.

for _host in ${_hosts}
do
        # Go out to the server and make sure it is AIX.
 If it's not, skip it.
        _uname=`ssh ${_ssh_opts} ${_host} "uname"`
        if [ "${_uname}" != "AIX" ]; then
                continue
        fi

        # Get the fileset level for bos.net.tcp.client
        _actual_host_level=`ssh ${_ssh_opts} ${_host} "lslpp -L bos.net.tcp.client | grep
 bos.net.tcp.client | awk '{ print \\$2 }'"`

The line above SSHs out to the server, ${_host}, and gets the value for the affected fileset—in this case bos.net.tcp.client.

        # Failure counter.
        _fail=0

        # Main loop.
        for _vulnerable_level in ${_vulnerable_levels[@]} #

(Notice the [@], which represents the entire array.)

        do
                # If the values from our array match actuals, then say so.
                if [ "${_actual_host_level}" = "${_vulnerable_level}" ]; then
                        printf "${_host} is vulnerable with bos.net.tcp.client of 
${_actual_host_level}.\n"     | tee -a rpc.scan.${_date}
                        _fail=`expr ${_fail} + 1`
                fi
        done

Here is the loop where we take the value of the fileset from our server and compare it to the filesets in our array.

        # If our failure counter hasn't gone off, then declare us not vulnerable.
        if [ ${_fail} -eq 0 ]; then
                printf "${_host} is not vulnerable.\n" | tee -a rpc.scan.${_date}
        fi
done

Perl One-Liners

Perl one-liners are extremely versatile tools. While probably not needed every day, they’re great to write down and keep handy, when needed. Having that perfect one-liner you need is often impressive to those around you. While, not critical, it’s kind of cool:

1. Convert Epoch (UNIX time; since January 1st 1970) to human readable time.

perl -e 'print scalar(localtime(EPOCHTIME)), "\n"'

Example:

[root@aix61-03]/root> perl -e 'print
 scalar(localtime(1342885345)), "\n"'
Sat Jul 21 11:42:25 2012

This one is very useful on AIX for determining the last time a user changed his or her password. To do so, look in the /etc/security/passwd file. It will look like this:

root:
        password = encryptedpassword
        lastupdate = 1311019884

So take the lastupdate epoch time number, and place it inside the perl parentheses to get the last time the password was changed.

2. Remove all blank lines from a file.

perl -ne 'print unless /^$/' FILE

Example:

This is our test file:

[root@gvicaix61-03]/root> cat test
This is a line

This is a space ^

This is two spaces ^

This is using our one-liner:

[root@aix61-03]/root> perl -ne 'print unless /^$/' test
This is a line
This is a space ^
This is two spaces ^

3. Insert line numbers on a file.

perl -ne 'print "$. $_"' FILE

Example:

[root@aix61-03]/root> perl -ne 'print "$. $_"' test
1 This is a line
2
3 This is a space ^
4
5
6 This is two spaces ^

As we moved beyond the basics of shell scripting, creating arrays, comparing values and understanding more advanced logic are important lessons to learn. The perl one-liners are an excellent resource to keep in your back pocket as well. In my next shell scripting article, we’ll dive into more advanced borne scripting, and introduce other languages well-suited for sysadmin tasks.

Leave a Reply