Article nov2006.tar

A New Approach to Account Activity Monitoring

Owen Stevens

My standard /etc/motd has always stated something like "Use of this system constitutes consent to monitoring..." The truth is that until recently, almost no monitoring was taking place. Sure, I use an endless variety of security tools and mechanisms to keep potential Bad Guys out of my systems, but what about the Good Guys? Once a user is authenticated, the motd is little more than an empty threat.

In my situation, there are three good reasons to monitor shell account activity. The first is, of course, security -- shell accounts are occasionally issued to consultants, vendors, and frequently to local end users. Although all of these users are essentially trusted, I cannot guarantee that their accounts will not be compromised or improperly used. Second, the ability to monitor account activity enhances my team's efficacy when troubleshooting end user sessions. Third, account monitoring satisfies some auditing requirements that are specified in corporate policies. Conversely, there is no good reason not to implement this functionality, as shell users on my production systems do not have any reasonable expectation of privacy.

During my time as a sys admin, I have often found myself trying to re-trace a user's steps. Typical Unix system configurations do not lend themselves well to this type of forensic investigation. There are only four basic tools at our disposal: the lastlog (or equivalent), shell history files, the sudo log (if applicable), and the find command.

I usually start by examining the lastlog to determine the relevant login times of the account in question. Although reliable, the information provided is minimal. I then refer to the shell history file associated with the account. This method has several major drawbacks. History files do not timestamp entries or separate sessions, therefore it can be difficult to correlate shell history with the information contained in the lastlog. Users obviously need write permissions to their own history files, a necessity that all but eliminates their usefulness as a monitoring component. The sudo log is only useful when the account has access to privileged commands, although it does a decent job of logging both successful and failed attempts in those instances. Both the sudo log and the shell history file are similarly limited when they record the execution of an interactive command. When interactive commands are executed, only the command itself is logged; any subsequent interaction is not recorded. In the cases of missing or incomplete shell history files, I can use the find command to list files owned or writable by the account, that have been modified since a given time. At this point, I have completely given up any pretense of monitoring and am merely searching for clues.

To live up to the claims I implied in /etc/motd, I need to dramatically improve my ability to monitor user account activity. As I set out to accomplish this, I soon became aware of a significant limitation -- any solution will inevitably involve some process invoked by the user at login. It follows that the user will thereby have write access to any files created by such a process, as well as the ability to terminate the process. Resolution of this core issue precedes any reasonable claim of progress. I considered various options, but each one invariably led me back to the same paradoxical problem, until I eventually devised an acceptable response.

The Access Server

I decided to "wrap" access to the server in question by introducing an intermediary server to which users must connect as the prerequisite path to their intended destination server. This "access server" can be a small PC running Linux, on which the user has almost no privileges. The access server performs three essential duties: it handles user authentication, session monitoring, and connectivity to the "destination server". All of these should occur with complete transparency from a user perspective. I began by setting up user accounts on the access server to match those on the destination server. Because I don't want the users to have to enter their password twice, I set up ssh keypairs that use a null passphrase for each account. Once a user authenticates on the access server, a connection to the destination server can be established without any further interaction from the user. This procedure is often referred to as "passwordless ssh", which I won't cover in this article because suitable tutorials are readily available on the Internet.

Session monitoring is accomplished on the access server with screen, which is invoked by the user at login. To ensure that the user has no other privileges on the access server, I need to make some rather debilitating changes to /etc/bashrc and /etc/profile. I'm okay with doing this because the access server has no other role in my infrastructure. In addition to these changes, I also need to disable the sftp subsystem in the sshd_config file, and ensure that the access server will not run any network services in addition to sshd. I have now restricted all non-root users to a screen session, which logs their activity and initiates a connection to the destination server. When this process exits, the user is logged off the system, and because exec is used, there is no opportunity for the user to break into a local shell. Although users have write permissions to their own logs, there is no available interface to these files. The relevant changes in each file are shown below. /etc/bashrc:

# /etc/bashrc 
[...] 
# Effectively disable scp by echoing something to STDOUT at login: 
/bin/echo "scp disabled"
            
and /etc/profile:

# /etc/profile 
[...] 
if [ "$USER" != "root" ]; then 
        exec /usr/bin/screen -l -L -q -s \
          '/usr/local/bin/connect.sh' -c /etc/screenrc 
        exit 
fi 
# 
A working screen installation is assumed in /etc/profile. The two necessary files, connect.sh, and screenrc, are shown below. /etc/screenrc:

# /etc/screenrc 
[...] 
logtstamp on 
logfile "/var/log/screenlogs/screenlog.%c:%s"
#
and /usr/local/bin/connect.sh:

#!/bin/bash 
# /usr/local/bin/connect.sh 
/usr/bin/ssh $USER@destination.domain.net 
# 
Any session on the destination server can now be monitored (with a slight delay) by the superuser who runs tail -f on the corresponding screen log file on the access server. Screen log files can be retained or moved to a backup tape for archival purposes. With this approach, account monitoring cannot be tampered with, even after a successful privilege escalation attack on the destination server.

The Destination Server

On the destination server, there are a couple of slight changes to make. I'd like to set the maximum number of concurrent sessions to one per non-root account, to ensure linear creation of the screen logs on the access server. I'll also use a host-based firewall on this server to deny ssh connections that do not originate from the access server. This step guarantees that the access server is used every time. Due to excellent documentation of host-based firewalls available on the Internet, I'll skip discussing this step any further. Here is the stanza in /etc/profile that limits the number of sessions:

# /etc/profile 
[...] 
# Only one concurrent session per non-root account allowed 

readonly INSTANCES=`w|awk '{print $1}'|grep -w `whoami`|wc -l' 
if [ "$INSTANCES" -gt 1 ] && [ b$USERb != brootb ]; then 
  stty susp ^- intr ^- eof ^- quit ^- 
  echo "You are already logged in."
  sleep 5 
  exit 
fi 
# 
    
Now that session activity is properly recorded, I'd like to incorporate a notification method that can be used on selected accounts. When vendors and consultants use their shell accounts, I'd like to be independently notified and have the option to review their work. I would also like to be alerted to account activity whenever I am troubleshooting or investigating a specific account over a period of more than one day. I have found AIDE to be very useful for this purpose.

Typically, vendor accounts may have sudo access to specified commands, and they may have write access to application configuration files, and sometimes database access. For each account, I identify any pertinent files and directories. The level of granularity varies considerably between accounts; of course, each particular situation must be analyzed. I'll demonstrate a basic example configuration of /etc/aide.conf. If the vendor1 user modifies any file in his home directory, or modifies his crontab, then this activity will be detected:

# Configuration file for AIDE 
@@define DBDIR /var/lib/aide 
database=file:@@{DBDIR}/aide.db.gz 
database_out=file:@@{DBDIR}/aide.db.gz 
gzip_dbout=yes 
verbose=20 
report_url=file:/var/log/aide.log 
report_url=stdout 
[...] 
# Custom Rules 
FILE = p+i+u+g+n+s+b+m+c+md5 
DIR = p+i+u+g 

# Files and directories to monitor: 

=/home/vendor1$                         DIR 

/var/spool/cron/vendor1                 FILE 
# 
Notice that this AIDE configuration differs from the standard recommended practice; the archive log and the initialized log are the same. That's because I'm going to run /usr/sbin/aide from cron and, if any changes are detected, I'll receive a report via email. The cron job will then reinitialize the AIDE database by running /usr/sbin/aide -i. This way, any detected changes will only be reported once. Here is an example detail from the report, in this case indicating a modified crontab file:

File: /var/spool/cron/vendor1 
  Size     : 684                               , 629 
  Mtime    : 2006-04-21 10:31:55               , 2006-07-05 12:07:04 
  Ctime    : 2006-02-09 22:32:22               , 2006-07-05 12:07:04 
  Inode    : 7209157                           , 7209134 
  MD5      : kAe8EKx2mXQmmrSbAitp7A==          , 
N/Sr/vD3/7oQ0UnyK4fbmA= 
# 
    
Putting It All Together

Finally, I recommend configuring ntpd on both servers so that the clocks on both these systems are synchronized. This step will greatly assist any future forensic use of the screen logs. With this accomplished, I have deployed an effective combination of ssh and screen within an enforced shell environment, which records session activity in a tamper-resistant fashion. The resulting logs provide detail superior to anything previously available, and this functionality has been deployed without interruption of service or negative user experience. My team also now has a valuable session troubleshooting resource.

I'm sure that nobody actually reads /etc/motd, but I like to think it can have a little more weight than expected. On my systems, you can take it to the bank.

Owen Stevens is currently employed as the Senior Systems Administrator for a medium-sized online retailer. He has more than eight years of experience as a Unix/Linux Administrator and runs a small consultancy. Owen can be contacted at: ostevens@gmail.com.