Per-user accounting has been a feature of ksh93 since the earliest days of this shell. It is a fairly primative facility which writes out an (undocumented) record for each user command that is executed.
An auditing facility was added in July 2008. This is somewhat more sophisticated than the accounting facility in that it is configurable and writes out a more detailed record either locally or to a remote system for each user command that is executed. This facility can be used to monitor, track, record, and audit the activities of one or more users on an system, including system administrators.
Both facilities only work for interactive users. Neither facility is enabled by default. In fact, you have to go into the ksh93 source code, modify the main Makefile to enable certain compile time options, and then recompile the sources. This is not a trivial exercise in many cases as rebuilding ksh93 also requires that you to rebuild a number of libraries. Source code is available at the AT&T Research AST software download site.
To build ksh93 with these facilities enabled, you must build the ksh93 executable using either the ast-base or ast-open package together with the INIT package. Just as the shared libraries are not built if you use the ast-ksh package, neither are the accounting and auditing facilities. I have never investigated why this is so, but I am sure that Glenn Fowler and David Korn have their reasons.
You need to modify the compile time options in ../src/cmd/ksh93/Makefile as follows to enable one or both facilities.
SHOPT_ACCT == 1 /* accounting */
SHOPT_ACCTFILE == 1 /* per user accounting info */
SHOPT_AUDIT == 1 /* auditing */
SHOPT_AUDITFILE == "/etc/ksh_audit" /* auditing file */
bash-3.2$ pwd
/home/fpm/ksh/build/arch/linux.i386-64/bin
bash-3.2$ ls -al ksh
-rwxr-xr-x 1 fpm fpm 1356931 2008-12-26 16:31 ksh
bash-3.2$ ./ksh
$ echo ${.sh.version}
Version AJLM 93t+ 2008-12-10
$ echo $KSH_VERSION
Version AJLM 93t+ 2008-12-10
Per-user accounting is enabled using the SHACCT environmental variable. To turn on per-user accounting, simply set SHACCT to the name of the file where you wish to store the accounting records.
export SHACCT="/tmp/ksh_acctfile"
$ cat /tmp/ksh_acctfile
echo ${.sh.version} fpm 495990d8
pwd fpm 495990da
id fpm 495990dd
date fpm 495990e3
exit fpm 495990e5
#!/bin/ksh93
ACCTFILE="/tmp/ksh_acctfile"
printf "DATE TIME LOGIN COMMAMD\n\n"
# set IFS to TAB only
while IFS=" " read cmdstr name hexseconds
do
longsecs=$(printf "%ld" "0x${hexseconds}")
timestr=$(printf "%(%Y-%m-%d %H:%M:%S)T" "#${longsecs}")
print $timestr, $name, "$cmdstr"
done < $ACCTFILE
$ ./parse_acctfile
DATE TIME LOGIN COMMAMD
2008-12-29 22:09:12, fpm, echo ${.sh.version}
2008-12-29 22:09:14, fpm, pwd
2008-12-29 22:09:17, fpm, id
2008-12-29 22:09:23, fpm, date
2008-12-29 22:09:25, fpm, exit
$ cat /etc/ksh_audit
/tmp/ksh_auditfile;500
Here are the audit records stored in the /tmp/ksh_auditfile which match the accounting records shown previously in this post. The field separator is a semi-colon. The first field is the UID of the user executing the command. The second field is the time in seconds since the Epoch. The third field is the terminal device on which the command was executed, and the final field is the actual command executed by the user.
500;1230606552;/dev/pts/2; echo ${.sh.version}
500;1230606554;/dev/pts/2; pwd
500;1230606557;/dev/pts/2; id
500;1230606563;/dev/pts/2; date
500;1230606565;/dev/pts/2; exit
#!/bin/ksh93
AUDITFILE="/tmp/ksh_auditfile"
while IFS=";" read uid sec tty cmdstr
do
name=""
while IFS=":" read pwname pword pwuid rest
do
if [[ "$uid" == "$pwuid" ]]
then
name=$pwname
break
fi
done < /etc/passwd
timestr=$(printf "%(%Y-%m-%d %H:%M:%S)T" "#$sec")
print "$timestr", $name, $uid, $tty, "$cmdstr"
done < $AUDITFILE
2008-12-29 22:09:12, fpm, 500, /dev/pts/2, echo ${.sh.version}
2008-12-29 22:09:14, fpm, 500, /dev/pts/2, pwd
2008-12-29 22:09:17, fpm, 500, /dev/pts/2, id
2008-12-29 22:09:23, fpm, 500, /dev/pts/2, date
2008-12-29 22:09:25, fpm, 500, /dev/pts/2, exit
/dev/udp/192.168.0.99/514;500
2008-12-29 22:09:12 192,169.0.115 500;1230606552;/dev/pts/2; echo ${.sh.version}
2008-12-29 22:09:14 192.169.0.115 500;1230606554;/dev/pts/2; pwd
2008-12-29 22:09:17 192.169.0.115 500;1230606557;/dev/pts/2; id
2008-12-29 22:09:23 192.169.0.115 500;1230606563;/dev/pts/2; date
2008-12-29 22:09:25 192.169.0.115 500;1230606565;/dev/pts/2; exit
Note that while the auditing and accounting facilities within ksh93 can provide you with much useful information regarding the actions of one or more users on a system or systems, these facilities should not be regarded as providing enhanced security akin to the Trusted Computing Base (TCB). There are many ways of circumventing these facilities. For example, a knowledgeable user could switch to a different shell such as bash where their actions will not be recorded. There are a number of other ways but I will not discuss them here.
Most of the information provided in this post is not documented in a single place anywhere that I can find by searching the Internet. The ksh93 man page does not mention either the accounting or auditing facilities. Even the ksh93 source code is somewhat vague. I gleened most of this information by studying the code in ../src/cmd/ksh93/edit/history.c. If I got anything wrong, please let me know so that I can update this post.
2 comments:
I spent some time with the auditing function and i had to realize that
-tha config file must be world readable (..must be readable by the user whose activites are audited)
-the logfile must be writable by all users whose activities are audited/logged.
Thanks for the parsing scripts :)
As the person who requested the feature be added, the key is not to truly prevent malicious behavior, but to provide a record of probable points where the logging was bypassed.
The issue is that we are asked to provide a record of actions taken with administrative privilege for numerous audits. By setting it to monitor the effective UID 0, (something that isn't clear, it looks at euid, not just real uid), we can centralize the shell history of multiple system administrators. As you correctly point out, it can be bypassed, but the bypass command will still be captured, and if you are logging offhost, it will be captured and recorded.
I strongly advise use of the /dev/udp/hostname/514 destination to log the results, that sends it to a remote box's syslog.
Post a Comment