Eventually in almost every incident response situation, you have to start contacting the actual people who sit at the keyboard of affected stations. Often you'll want them to step back from the keyboard or logout, for either remote forensics data collection or for remediation. Or in the worst case, if you don't have remote re-imaging working in your shop, to either ship their station back to home base for re-imaging or to arrange a local resource to re-image the machien the hard way.
Long story short, what this means is that you need the name of the principal user of that station, and their phone number, preferably their cell number. Time is usually of the essence in IR, and you can't always count on or wait for email or voicemail (or VOIP phones either...). What you will usually find is that often stations will pass from hand-to-hand, outside of IT's control. It's pretty common for managers in remote locations to "stash" a user's laptop when they leave the company, either as a spare or just to be handy when the next new hire gets onboarded. It's also not unheard of for the IT folks re-deploying workstations to make clerical errors as they assign devices (or just plain skip the updates).
What that means is that the hardware / OS / software inventory scripts that we've covered in the past only cover 3 or the 4 facets of the actual inventory. We want to add Userid, Full Username, City / Address and Extension and full phone / cell phone number. What this also implies is that you want your AD administrators to work more closely with both the telephone and cell phone admins and with HR. If you use the methods outlined below, it also implies that you'll be populating the appropriate AD fields with accurate contact information.
First, how do we get the currently logged in user? We've had methods to do this since forever, a few of them are:
Arguably the easiest method is to use pstools. psloggedin.exe will get you the currently logged in user by scanning the HKEY_USERS registry hive to get logged in User's SIDs, then users NetSessionEnum API go get the user name. And, just like psexec, psloggedin will "find a way" - it'll generally enable what it needs to get the job done, then back out the changes after the data collection is complete.
How does this look? See below (the -l enumerates only locally logged in user accounts)
Note however that this means that you'll need to loop through each station, and that the station needs to be online to collect this information.
WMIC also does a good job, with similar (and and similarly limited) results.
"nbtstat -a <computername>" was the way to get this info back in the day, but I'm not seeing great success with this command in a modern network.
Query.exe and qwinsta both still work great though:
More importantly, these all give us the username as a string, with lots of other cruft all around the one string of interest. This is fine for 1-2-3 hosts, but if you're collecting info for hundreds or thousands of hosts, not so much.
How about adding user collection to our previous hardware inventory script (in PowerShell)? This is pretty easy also, and also allows us to add in our contact details.
To get a logged in user:
(Get-CimInstance works exactly the same way)
Parsing this out to just the username string:
What if our user isn't logged in, but the machine is powered on? In that case, we're digging into the security event log on that machine, looking for event id 4624. In some cases we'll see multiple users logging into a computer, so we'll go back "N" days, and pick the user with the largest count of logins as our principal user for that station. Note that logon type 2 is a local interactive login, so that's what we're looking for in "$event.properties.value -eq 2". An alternative view is that you'll want to collect all the users of that host, since the principal user might not be available when you call.
Now, on the AD side, let's add in the infomation collection for phone and email info:
Finally, adding the hardware info from our existing hardware inventory script, we can join the two blocks of information by workstation name, using DNS (we'll do this in a few paragraphs). This is more reliable than just using the IP address returned in $pcs, as workstations commonly now have both wired and wireless IPs, so that field is not our most reliable bit of info.
How about if we need to get the username for a station that's powered off or disconnected? Remember that during a security incident that target machine might not be operable, or it might be remote. That's a bit more time consuming, we'll need to query AD for users who have logged into the target station. If multiple users have logged in, then most likely we'll want the person who has logged in the most, or the complete list with a count for each user. More useful, a database of all stations and logins can be refreshed weekly, then used to verify our inventory database or just saved so that we have current information in the event of an incident.
In preparation for this, you'll want to ensure that you are logging all user logins. The best advice is that you want both successful and failed logins (for obvious reasons), though for this application we need successful logins. In group policy editor, these settings are at:
And yes, for reasons unknown Microsoft has these both disabled by default (most vendors follow this same not-so-intuitive path). Maybe some 1990's reason like "disk is expensive" or something ...
Anyway, with that enabled, we can now query the event log:
To harvest the information of interest, the fields we want are:
$events[n].Properties for the userid
This will get you close to a final "userid + contacts + workstation" database. What you'll likely want to add is any additional filters, maybe to remove any VDI station logins, named-user-admin accounts and so on. If you are seeing ANONYMOUS logins, logins with the built-in "Administrator" accounts, service accounts and so on, you'll likely want to filter those top, but maybe investigate them first.
At some point you'll have some manual edits to do, but a script like this can go a long way towards verifying an existing inventory and contact database, creating a new one from scratch, or just a handy "who logs into what" list with phone numbers. Remember, for IR you're not so much concerned with who "owns" a station as to who logs into it often (so you can find those people and then physicall find that station).
As always, I'll have this script in my github, https://github.com/robvandenbrink - look in "Critical Controls / CC01"
If you can, try a script like this in your environment, then user our comment form to let us know if you find anything "odd".
Feb 20th 2020
Feb 20th 2020
6 months ago
Nice script - but it requires some kind of additional rights to be able to run this against the DC. According to this post (https://social.technet.microsoft.com/Forums/lync/en-US/b72162d1-2c86-4d1a-9727-ec7269814cc4/getwinevent-with-nonadministrative-user?forum=winserverpowershell) you need to modify rights on the registry. Is that right? I don't want to muck around with the DC unless I really have to.
Feb 24th 2020
6 months ago