0

In our company we usually have a single production user user and we ssh to our servers via pasword-less login with ssh keys.

Now, quite a few people work on those servers and sometimes we need to understand why changes were made and who made them. For that we would like to audit bash commands but we also need to preserve the original remote user id. This explains how to define ${REMOTE_USER} variable but how can we store it in history/audit logs for each command?

Roman
  • 133
  • 7
  • What you really need is a configuration management system like e.g. puppet or ansible (there are others too) and documented procedures for change management. It may take some pain to set up but in the long run you will benefit from doing so. – user9517 Dec 26 '18 at 19:22
  • You also need people to _not_ share accounts, ever. That's such a massive security fail that you're pretty much guaranteed to fail any audit of any consequence. – Michael Hampton Dec 26 '18 at 21:22
  • We use ansible and we do not share personal accounts. I am talking about "service" account on production servers. Engineers and DevOps login into service account and might make changes. I would like to record them to allow better transparency when debugging problems later – Roman Dec 27 '18 at 19:09
  • Related: [Is it possible to get OpenSSH to log the public key that was used in authentication?](https://serverfault.com/q/291763/126632) – Michael Hampton Dec 28 '18 at 22:07

1 Answers1

3

Ideally, it's best to provision everyone with their own ssh keypair, their own login account and use sudo to track who's doing what, and where. If you don't have centralized authentication and more than a couple servers, maintaining all those login accounts can be a mess (note: see ansible for an easier way without LDAP) not to mention maintaining password changes.

What I've done in the past, is require the remote user to export a variable on their system named LC_SSH_USER. This variable can be accepted by the sshd config via the AcceptEnv LANG LC_* setting. A script in /etc/profile.d runs on login and "sanitizes" the variable and/or terminates the connection if the variable is not found. Additionally, the readonly attribute is set on the variable so inadvertent changes to the variable cannot easily be made. This way, no matter what account the remote user had logged into (www-data, passenger, admin) the originating user is logged. The system can be circumvented easily enough by the user setting their variable to whatever they want however an HR policy can be put in place to deal with it.

sample script to place in /etc/profile.d/lc-ssh-user.sh which will log LC_SSH_USER to /var/log/auth.log (on Ubuntu) :

# only allow letters, numbers and underscores in passed LC_SSH_USER variable
lc_ssh_user_sanitize()
{
   arg="{$1}"
   # first, strip underscores
   clean="${arg//_/}"

   # next, replace spaces with underscores
   clean="${clean// /_}"

   # now, clean out anything that's not alphanumeric or an underscore
   ret="${clean//[^a-zA-Z0-9_]/}"

   echo "${ret}"
}

# if SSH_CLIENT is not set, and LC_SSH_USER is not set, then this is a local login or a new shell opened by same user
if [ -z "${SSH_CLIENT}" ] && [ -z "${LC_SSH_USER}" ]; then
   export LC_SSH_USER=${USER}
else
   # otherwise, this is an ssh session - extract the connecting IP from env
   con=`echo "${SSH_CLIENT}" | cut -d'=' -f2 | cut -d' ' -f1`

   # export some variables needed for the user environment
   # when using "su --preserve-environment  userxxx --login" be sure to fixup needed variables
   export USER=`whoami`
   export LOGNAME=${USER}
   export HOME=$( getent passwd "$USER" | cut -d: -f6 )
   cd ${HOME}

   # user login without LC_SSH_USER set on their local machine
   if [ -z "${LC_SSH_USER}" ]; then
      echo "Error: LC_SSH_USER not set in connection from ${con} as user $USER" | logger -p auth.info
      #
      # connection could probably be terminated here to enforce the use of LC_SSH_USER
      #

      # since there is no LC_SSH_USER in the connection, just use whatever the user logged in as
      export LC_SSH_USER=${USER}
      echo "Notice: LC_SSH_USER set from login ${USER} from ${con}" | logger -p auth.info
   else
      # user has LC_SSH_USER set, so sanitize it (just in case) and log the sanitized version to syslog via logger
      u_sanitized=$(lc_ssh_user_sanitize "${LC_SSH_USER}")
      echo "Notice: LC_SSH_USER ${u_sanitized} login from ${con} as user $USER" | logger -p auth.info
   fi
fi

# always make LC_SSH_USER  readonly in the users environment
readonly LC_SSH_USER

Update: git commit hook to use $LC_SSH_USER:

#!/bin/sh
# To enable this hook drop this in ".git/hooks/pre-commit" (chmod 0755)
# It will create .commit_template if it does not exist
# add these lines to .git/config:
# [commit]
#   template = .commit_template
#
test -f .commit_template && exit 
echo "
Fix   : 
Issue : 
Author: $LC_SSH_USER
" > .commit_template
Server Fault
  • 3,454
  • 7
  • 48
  • 88
  • Do you know how to log LC_SSH_USER in bash history logs or in auditd logs? – Roman Dec 27 '18 at 19:10
  • I've added a script you could use to put the info in the system logs. The `LC_SSH_USER` variable ends up exported into the user's environment like any other variable. You could add other initialization in the profile script or user's ~/.bashrc if needed. Be careful when editing the script. If you botch it in-place, not even root can login to fix it (get a boot CD on hand). – Server Fault Dec 27 '18 at 19:35
  • with lc env set you can use one login user for all users but you should still use multiple ssh keys for security – Andreas Rehm Dec 27 '18 at 19:51
  • @AndreasRehm - Yep. Additionally, this opens a potential for exploit (shellshock in the past) as it accepts input from the client which gets imported into a shell session. The `sanitize()` function tries to mitigate but nothing's ever perfect. – Server Fault Dec 27 '18 at 19:55
  • That's perfect, thanks! We use ssh key per user, of course. The goal is not to handle malicious intruders, the goal is to audit human-applied changes. This solution works well enough. – Roman Dec 28 '18 at 20:23
  • You're welcome. I added a git commit hook to my answer which could be used to leverage the $LC_SSH_USER to drop the info automatically into git logs. – Server Fault Dec 28 '18 at 21:18