Checking for disabled/deleted accounts with Halo

I wrote a blog post about using CSM to check that an account has been disabled.  Since I wrote that, it occurs to me that there’s more to it.

First, we almost always want to check that an account owned by a former employee is disabled – that neither they nor anyone else can use it.  Depending on company policy, we may also want to check that it’s been deleted.  This post covers the checks you’ll need for either goal, as well as a few extra checks for completeness.

These checks should work whether the account has been disabled, has been completely removed, or never existed at all.  For that reason, they’re all written as “so-and-so should not exist”.

Specific checks for a disabled account

We’ll use “jparker” as our example of a recently terminated employee.  As part of the normal exit procedure their accounts should already have been disabled or removed; creating these checks allows us to confirm that this has been done on all servers.

1) Password field locked

Does not contain

This check is a little odd as it contains a double negative.  It’s saying “Make sure there’s no line starting with jparker with anything other than an “!”, an “*”, or a “:” in the second column.  It will fail and alert if you have a normal password hash there, but will pass and stay quiet if the account is locked with a starting ! or *.


2) Account disabled field has a date in it

Does not contain


For disabled accounts, we’d like the SAM module to recognize that an account is Inactive/Disabled.  To make sure it’s reported that way, you must both lock the /etc/shadow password field and put a “disabled date” in column 8 of /etc/shadow.

Using the “Disable account” feature in the Halo portal SAM module or the Halo API performs the above 2 steps.  If you need to lock the account from the command line, use “usermod -e 1 -L jparker”, and to unlock the account, use “usermod -e 9999-12-31 -U jparker” .  Both commands need to be run as root.

3) .rhosts doesn’t exist

Does not exist.

(You don’t need to do the same for .ssh’s authorized_keys or authorized_keys2, as ssh detects that the account has been disabled and refuses to honor those keys.)

If you also require the account to be completely gone, add:

should not exist.


should not contain

You don’t need to check that /etc/group doesn’t contain ^jparker: as well; even if this line existed, it doesn’t give the user jparker any access to reach the system.  Similarly, there’s no need to check /etc/shadow or /etc/gshadow.

Optional checks for either approach

6) User has not logged in in the last 90 days

jparker has not logged in in the last 90 days.  Adjust to fit when user left.

7) /etc/hosts.equiv should not exist.

If you use the “r-commands” for remote access and this file needs to exist, at least put in File String Presence checks to make sure there are no lines with ^jparker or ^+ .

8) /etc/sudoers should not contain ^jparker .  Granted, if jparker can’t log in he/she can’t run sudo, but this is a good defensive measure.

9) /var/spool/mail/jparker should not exist.

10) If jparker might have owned any files outside of his/her home directory, you may also want to put one of the “ownership” checks (File User Ownership, File Group Ownership, Directory User Ownership, or Directory Group Ownership) for any files that might be owned by them, such as “/home/webcontent should be owned by user msmith”.

By including some or all of these checks in a single policy applied to all your server groups, you can be sure that the account is unusable, gone, and/or completely removed from the system.

Stay up to date

Get the latest news and tips on protecting critical business assets.

Related Posts