Sunday, November 18, 2007

Making Generic User Accounts Su-Only!

It's generally good practice, as an administrator, to make sure that you'll be able to account for who was on what box and when, just in case something bad ever happens and the higher-ups want an explanation.

This issue generally comes up with "generic" (or group-used) accounts that are directly accessible. If anyone can log into the "genericAccountName" user account, it's harder to establish an audit trail, since you have to start outside of the box on which your investigation should be centering.

Fortunately, it's relatively simple to set up "generic" user accounts so that users have to log on to your server as themselves first, and then su to that account. This means you'll be able to look at the output from "last" and the "su log" to quickly determine who was logged in as the "generic" user at any given point in time.

The steps to setting up a "generic" account so that its bound by these restrictions (and is still usable) are the following (substitute the appropriate profile file if you're not using ksh or sh):

1. Give the user's .profile 755 permissions and make it owned by root:root, so the user can't edit it or change its permissions.

2. At the end of the .profile, source in another file (.kshrc or something) so that users can still modify their environment, to suit their needs, once they've su'ed to the account.

3. In the .profile that you've made "755 root:root" do a simple check to see if "logname" matches the account name. I suggest using "logname" because that's set by the login program and never changes; even if you su. The $LOGNAME variable, on the other hand, can be changed and is easy to manipulate. Something like this should be sufficient:

if [ `logname` == "genericAccountName" ]
then
echo a message here
exit
fi


4. You should also check the value of "$-" in the system's /etc/profile (specifically look for the "i" in the output) and make sure that you don't allow commands to be executed in a non-interactive shell (you need to do this in /etc/profile instead of the user's .profile as a non-interactive session won't read the .profile). If you allow non-interactive shell access, users won't be able to log in and work, but they will still be able to use ssh, or rlogin, to execute commands remotely and directly, as such:

ssh genericAccountName@host.xyz.com "ls"

5. If the "generic" account needs to run cron jobs under its own identity, the simple check at the beginning of the .profile will keep their cron jobs from executing (That is, when cron executes and reads their .profile, the initial check will indicate that "logname" equals the "generic" accout name and fail). The easiest fix for this is to put an additional check in the user's root-owned .profile to allow direct login as long as the user is already on the host (I know that sounds goofy, since you can't invoke the "login" command as a user once you're on the box, but that's essentially what cron will do). You can verify the host info with the "w" command like:

if [ `w \`logname\`|sed 1,2d|awk '{print $3}'` == hostname ]
then
the user is initiating the login from the host - it's okay
fi


combine that with the basic "logname" check, however you like, and the "generic" user can still use cron even though the account is now "su-only."

And that should make it so people can't login to your machine directly, and ensure that they will have to su to the "generic" account. This is great for a cheapo-quickie audit trail and should save you a good deal of time if that "generic" account is used improperly or is involved in causing any other issues.

, Mike