Wednesday, March 25, 2009

Episode #15: New User Created When?

Last week, Mr. Byte Bucket (middle name "Mercy"), posed a kung fu challenge to me based on a discussion in the pauldotcom IRC channel. He asked:

"How can I determine the account creation time for a local account on a Windows host from the command-line?"

Folks in the channel had suggested:

C:\> wmic useraccount get name,localaccount,installdate

Unfortunately, the installdate is never populated, so we can't get any love there.

Another suggested:

C:\> net user [UserName]

That's a little better, in that it has some actual data. But, the dates it contains are when the password was last set. If the password was set at account creation, it'll be the creation date. But, that inference might be a bit much.

An item I've found very helpful that is a somewhat close proxy for account creation time is the time that the account is first used to logon to the box. We can see that by looking at the creation date of the home directory of the account:

C:\> dir /tc "C:\Documents and Settings\"

Or, on Vista, where they moved User accounts by default to C:\users:

C:\> dir /tc C:\Users\

As we've seen in past episodes, /t means time, and the c option means creation time. Look at the creation time of the directory of the user your are interested in, and that's often even more useful than the original creation time of the account itself.

But, it's kind of side-skirting the issue, no? How can you find the actual time of account creation, independent of its use to logon? For that, we can turn to the event logs, provided the system is configured to "Audit account management", which sadly, is turned off by default.

If you have it turned on, though, you can query it on XP Pro using the great built-in VBS script called eventquery.vbs, used thusly:

C:\> cscript c:\windows\system32\eventquery.vbs /L security /FI "id eq 642"

That shows us what we want on Windows XP and 2003 Server. Frustratingly, our great buddies at Microsoft removed eventquery.vbs from Vista. Thanks for nuthin' guys.

But, what Microsoft takes, the often give back, in a completely different and far more complex and bewildering form. In place of eventquery.vbs, we now get wevtutil, a command-line tool for interacting with event logs. We can query logs using:

C:\> wevtutil qe security /f:text "/q:*[System[(EventID=4720)]]" | more

The wevtutil query syntax is impossibly complex, and something I frankly loath. Note that you have to get the case right on EventID or else it won't work. But, this command will show you a huge amount of information about any accounts created locally on the system, including the date, time, SID creating the account, SID of the created account, UAC settings for the account, and so on.

Fun, fun, fun!

Hal Says:

I really wish I could claim that Linux and Unix were somehow superior to Windows in terms of solving this problem, but like Windows we don't track account creation events as a general rule. Obviously there are exceptions because of additional levels of logging, such as when you use sudo to create accounts or enable kernel-level auditing. However, even these approaches could be subverted by a clever attacker.

So we're left using the same sorts of proxies that Ed uses in his Windows example. You can normally find the date of last password change in the third field of a user's /etc/shadow entry:

hal:<hash censored>:14303:0:99999:7:::

The value is in days since the beginning of the Unix "epoch" (Jan 1, 1970). If you happen to have the "convdate" program installed (it's part of the "inn" package on my Red Hat systems), you can use it to convert these dates:

# /usr/lib/news/bin/convdate -c \
`awk -F: '/^hal:/ {print $3 * 86400}' /etc/shadow`

Fri Feb 27 16:00:00 2009

"convdate -c" converts the number of seconds since the Unix epoch to a human-readable date. So we use awk to extract the third field of my /etc/shadow entry and multiply this value by 86400 (24hrs * 60min * 60sec).

There are some problems with this approach, however. First, as Ed points out, this only gets you the time of the last password change for the user. If you force users to change passwords regularly, this will only get you the creation time of recently created accounts. Second, this approach only works if you keep user account information in the local passwd and shadow files-- if you use directory services like Kerberos and LDAP, then all bets are off. Third, it's certainly possible for an attacker who's broken root to create a local account and modify the third field of /etc/shadow, or simply not populate this field to begin with.

Ed's next suggestion is to look at the creation date on the user's home directory. As I mentioned in Episode #11, Unix doesn't track creation times on files. So you're left with using inode numbers as suggested in Episode #11 in order to make a guess at relative creation dates of different user home directories. It might actually be more fruitful to look at the last modified times on various "dot files" in the user's home directory, since users don't tend to mess around with these much once they get their environment customized the way they want it:

# ls -ltd /home/hal/.[^.]* | tail -1
-rw-r--r-- 1 hal users 1254 Aug 20 2007 /home/hal/.bashrc

There's a couple of interesting things going on in the command above. First we're telling "ls" to give us a detailed listing so we see the timestamps ("-l"), not to list the contents of matching directory names but just list the directories themselves ("-d"), and to sort the listing by last modified time with the most recent entries first ("-t"). Notice that we're also using the syntax ".[^.]*" just to match the dot files and directories without matching the ".." link that refers to the parent directory. "tail -1" just pulls off the oldest entry.

Still there are problems with this approach as well. The biggest problem is why would an attacker necessarily create a home directory for the back-door accounts they've created on your system? Even if they did do this for some reason, you can't trust the timestamps on the files because the attacker may have modified them-- even setting them backwards if they've successfully broken root.

How about Ed's idea of checking the first login date for the account? There are a couple of different places we could go to look for this. First we could use the "last" command to dump the wtmp log entries for a particular user in reverse chronological order (most recent to oldest):

# last hal | tail -3
hal pts/0 Mon Mar 9 07:02 - 10:02 (02:59)

wtmp begins Sun Mar 8 04:04:53 2009

As you can see from the output above, however, the wtmp logs normally get turned over every so often. It's possible that the first login for this user actually happened prior to March 8th, but we can't see it because it's no longer in the log.

There's also the Syslog stream for the system. Login events usually end up in a file like /var/log/auth.log or /var/log/secure (see /etc/syslog.conf for where "auth" logs end up on your particular flavor of Unix). Again, however, these logs normally get "rotated" on a regular basis, so you'll want to make sure you search the entire set of logs for the oldest entry:

# grep hal /var/log/secure* | tail
/var/log/secure.4:Mar 1 21:37:49 deer sshd[23446]: Accepted password for hal from port 12501 ssh2
/var/log/secure.4:Mar 1 21:37:49 deer sshd[23446]: pam_unix(sshd:session): session opened for user hal by (uid=0)
/var/log/secure.4:Mar 1 21:45:42 deer sshd[23446]: pam_unix(sshd:session): session closed for user hal

Notice that in fact these login events do pre-date the wtmp entries we saw from the "last" command above. But even these logs don't go much further back than our wtmp data and we're left to wonder if there were earlier login events that we're not seeing. By the way, since attackers who gain access to the system can modify the logs and remove traces of their logins, you're better off having a copy of these logs on a central, secure log server for your enterprise.

One thing you must to be aware of, however, is that both wtmp style and Syslog logging of user access is not mandatory on Unix systems. In other words, you get these logs because the application developers of SSH, /bin/login, etc have all decided to add the code to their applications to update the logs as appropriate. However, an attacker who plants a back door on your system is unlikely to elect to log the activity of that back door. So again you need to enable extra levels of logging like kernel-level auditing in order to have an application-independent log of events on the system.

Bottom line is that I suggest establishing an external control of some sort that monitors your user database (in whatever form it happens to live in) and alerts you to not only new account creations, but also account deletions, and account lock/unlock activity. You should probably also monitor for unauthorized changes to the passwords for "system" type accounts like root, oracle, and the database access accounts for web applications and the like.