Keeping an eye on troublesome users

Warning

Before implementing anything like this, make sure you run your plans past your local legal counsel. Invasion of privacy is a serious matter, and you might end up dangling off the end of the long arm of the law, or at the very least, losing your job. Ensure that you add a message in /etc/motd, informing users that ALL of their actions WILL be monitored.

Introduction

If you have a user who is attempting to do bad things to your system (or others' systems), you need to keep track of what's going on. Whilst viewing their ~username/.bash_history file (or similar) let's you see which commands the user has executed, it is all to easy for the user to remove the file, link to /dev/null, or just turn off history logging. The history file also does not show you command output, nor do the various accounting tools.

Whilst the following solution could still be circumvented by the knowledgable or devious user, it's usually enough to get the information (and/or evidence) that you require. This would generate a huge amount of output anyway, so you'd only want to enable it whilst your gathering information, then turn it off again. By which time the user probably wouldn't have realised that they'd been monitored in the first place.

A brief overview of the solution is as follows. A block of code added to /etc/profile will start a script session for each user that needs to be monitored. The script output is logged to a central directory. Periodically, a script runs via cron to bzip up old session logs, and change ownership and permissions so that they are secured. This script uses lsof to check that the log isn't being written to before securing it.

Prepartions

First, we need to create our central session directory. I'm using Gentoo Linux, and need lsof later, so I'll emerge that too.

    
# mkdir /var/session
# chmod 1777 /var/session
# ls -ld /var/session
drwxrwxrwt 2 root root 4096 Mar  7 09:16 /var/session
# export http_proxy="http://athena.mit:8080"
# emerge -s lsof
# emerge -pv lsof
# emerge -v lsof
   
  

Modifications to /etc/profile

You'll need to modify this if your users have different shells listed in /etc/passwd, but these days, most users have bash as their login shell.

Add a function that starts a script session for each user that you want to montior as they log in. Also ensure that the users shell initialisation files are executed too. .bashrc would be called from .bash_profile so doesn't need to be included.

    
function log_me {
  DATE="/usr/bin/date"  SCRIPT="/usr/bin/script"
  LOGBASE="/var/session"
  if [ -d "${LOGBASE}" ]; then
    TIMESTAMP="$( ${DATE} +%Y%m%d-%H%M )"
    LOGFILE="${LOGBASE}/${HOSTNAME}-${USER}-${TIMESTAMP}.$$" 
    umask 077
    [[ "${SHELL}" = "/bin/bash" && -e "${HOME}/.bash_profile" ]] && . ${HOME}/.bash_profile
    ${SCRIPT} -q ${LOGFILE}
    [[ "${SHELL}" = "/bin/bash" && -e "${HOME}/.bash_logout" ]] && . ${HOME}/.bash_logout
    logout
  fi
}

case ${USER} in
  kevtest|anyone|someone) log_me ;;
  *)                             ;;
esac
    
    

You can easily add users to the case block to have them logged. Here, the users kevtest, anyone and someone are logged.

This code will ensure that once the script session is exited, the user is logged out. If the user is a bash user, they also have the privilege of having their shell initialisation/logout files executed. Even though the canny user can still circumvent the logging with some crafting of his/her .bash_profile, most users are (for the most part) not going to notice what's going on.

Files are created under /var/session, owned by the user, with restricted permissions (as set by configuring the users umask in /etc/profile). Again, a canny user could hunt these files down and remove them, but unless they've got something to hide (and you see from 'last' output that they are logging into the system but no session files exist for them - and hence approach them), there's little chance of this.

Keeping Session Files Secure

In order to ensure that there is a minimal chance of the user modifying their old session data, implement a simple script such as the following and save it as /usr/local/sbin/session_files.sh. This script will find any session file that's not currently open (i.e. not being written to by an active session) and chown it root:root, whilst chmod'ing it 400. It will then bzip it, as script output can tend to grow quite large. Schedule this script to run via cron every 15 minutes.

    
#!/bin/bash

BZIP2="/bin/bzip2"
CHMOD="/bin/chmod"
CHOWN="/bin/chown"
ECHO="/bin/echo"
FIND="/usr/bin/find"
LSOF="/usr/sbin/lsof"
WC="/usr/bin/wc"

SESSIONROOT="/var/session"

function chmod_chown_file {
   local SESSIONFILE="$1"
   ${CHOWN} root:root ${SESSIONFILE}
   ${CHMOD} 400 ${SESSIONFILE}
}

function bzip_file {
   local SESSIONFILE="$1"
   ${BZIP2} -9 ${SESSIONFILE}
}

function check_open_file {
   local SESSIONFILE="$1"
   LINECOUNT=$( ${LSOF} ${SESSIONFILE} | ${WC} -l )
   if [ "${LINECOUNT}" -gt "0" ]; then
      return 1
   else
      return 0
   fi
}

${FIND} ${SESSIONROOT} -type f ! -name "*.bz2" | while read SESSIONFILE; do
   # assume that anything that isn't bzipped needs chmod and chown too
   check_open_file "${SESSIONFILE}"
   if [ "$?" -ne "0" ]; then
      ${ECHO} "${SESSIONFILE} is open. Ignoring."
   else
      chmod_chown_file "${SESSIONFILE}"
      bzip_file "${SESSIONFILE}"
      ${ECHO} "${SESSIONFILE} has been processed."
   fi
done

exit 0
   
    

Make this script executable

    
# chmod +x /usr/local/sbin/session_files.sh
   
    

Now, su - to once of the targetted users and check that logging is working correctly.

Conclusion

If malicious activity is a problem on your system, and you've been asked to get to the bottom of it, a solution such as this can (with proper authorisation) be your saviour.

Cheers
Kevin Waldron
kevin@zazzybob.com

Disclaimer! - This article is provided for guidance only, and does not replace the relevant official documentation and manuals. I will not be held liable for any hosed systems and/or data.

Valid CSS!

Valid HTML 4.01!