I put a call out for blog ideas: Devin Austin came up with “Login Accounting”. So let’s talk about that for a bit.
First off, a little disclaimer
This is not security advice, I am not a security expert, or an expert at pretty much anything. Use your head, silly.
Let’s also be clear about something
Login Accounting is pretty much a mess on unix. Programs that manage logins can “opt-in” to login accounting; the system does not inherently do this for you, largely by side effect of why it works at all. Most tools can even be configured to write to the basic accounting systems or not, or provide the option as a runtime argument. This means that your login accounting system can lie. Additionally, the systems we’re going to look at are the first thing an intruder will mess with. We’ll look at a few techniques to mitigate the lack of information later, but rest assured there’s not much you can do to make this bulletproof.
All code examples in this article expect Ubuntu 11.10 to be the platform. You will see deviation between systems so be certain you’ve absorbed this article before trying anywhere else.
utmp, wtmp, lastlog
These are the core systems in unix login accounting; they are append-only
databases, more or less, with a system-dependent structure. You can usually
read about the structure by typing
man utmp or reading the
/usr/include/utmp.h file. Note this will be dramatically different between
Linux, FreeBSD, Mac OS X, etc.
One can navigate the
utmp structure pretty simply, or use the
last commands to navigate them. They exist as three files:
/var/run/utmpis what’s currently going on.
/var/log/wtmpis what’s happened in the past.
/var/log/lastlogis the last account for each event (e.g., a specific user logging in)
Anyhow, let’s have some fun. As for navigating the structure, while
system-dependent that’s really easy. Here’s a small program that navigates
utmp and sends the pty and username to
figlet for output for all user-related
apt-get install build-essential figlet and then
gcc -std=c99 -o
fig_utmp fig_utmp.c to use.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
It outputs something like this (I’m holding two logins to the box):
_ ___ _ _ _ _ __ | |_ ___ / / | ___ _ __(_) | _| |__ | '_ \| __/ __| / /| | _____ / _ \ '__| | |/ / '_ \ | |_) | |_\__ \/ / | | |_____| | __/ | | | <| | | | | .__/ \__|___/_/ |_| \___|_| |_|_|\_\_| |_| |_| _ _____ _ _ _ _ __ | |_ ___ / / _ \ ___ _ __(_) | _| |__ | '_ \| __/ __| / / | | | _____ / _ \ '__| | |/ / '_ \ | |_) | |_\__ \/ /| |_| | |_____| | __/ | | | <| | | | | .__/ \__|___/_/ \___/ \___|_| |_|_|\_\_| |_| |_|
Try modifying it to output the hostname as well! (Hint: the struct member is called
utmp carries a lot more than just user logins though, it’s responsible for
recording most of the events that happen at a system level. For example, here’s
erikh@utmptest:~$ last erikh pts/0 speyside.local Sun Mar 25 10:18 - 10:18 (00:00) erikh pts/0 speyside.local Sun Mar 25 09:17 - 10:06 (00:48) reboot system boot 3.0.0-16-server Sun Mar 25 09:13 - 10:22 (01:08) erikh pts/1 speyside.local Sun Mar 25 09:13 - crash (00:00) erikh pts/0 speyside.local Sun Mar 25 09:12 - down (00:00) reboot system boot 3.0.0-16-server Sun Mar 25 09:11 - 09:13 (00:01) reboot system boot 3.0.0-16-server Thu Mar 22 00:35 - 00:53 (00:18) reboot system boot 3.0.0-16-server Thu Mar 22 00:32 - 00:33 (00:01) erikh pts/0 speyside.local Thu Mar 22 00:31 - down (00:00) erikh tty1 Thu Mar 22 00:27 - down (00:04) erikh tty1 Thu Mar 22 00:27 - 00:27 (00:00) reboot system boot 3.0.0-16-server Thu Mar 22 00:20 - 00:31 (00:11) erikh tty1 Thu Mar 22 00:16 - down (00:03) erikh tty1 Thu Mar 22 00:16 - 00:16 (00:00) reboot system boot 3.0.0-12-server Thu Mar 22 00:16 - 00:20 (00:03)
Notice all the reboots in there? This is why we filter on
ut_type contains a lot more information than what we care about. Anyhow,
this is explained better in
man utmp, so go read that. There is also the
utmpx which isn’t really any more consistent than
utmp is across
So, about this lossy login accounting issue…
What to do about it? There are really two options:
- Make sure your things are logging utmp entries.
- Use something else, like log scanning.
In reality only one of these is the serious choice — there are other things
auditd and PAM controls that can assist here, but not much really. Log
scanning and having tight control over how users get into your systems is the
way to go. Since log scanning is such a deep article, we’ll cover it in a
separate one. Stay Tuned.
utmp system is typically relied on for a lot more than it should be; it’s
inconclusive and generally flawed especially for non-interactive … interaction.