Let me start off by saying I am not against overemployment, in fact, I support whatever income streams you can make work. I have my own personal side gig that I keep completely separate, and it is a separate industry, and requires physical presence.
It's ok but...to the people you are working for, the contract needs to be clearly defined. Do they allow it? Do they measure performance based on results or by hours worked? If it's hours worked, I think you can get into hot water very quickly. A text here or an email there is not what I am talking about. I'm referring to people having two laptops open and just keeping plates spinning, or giving off the appearance of being online/available. Other cases the person is physically present, but spends a ton of time on their phone on other meetings and providing support. In some cases, people use the same laptop which may violate employment agreements for the company who owns the laptop.
Another caveat - I am not in search of a solution that will be a silver bullet in identifying overemployment, or even one that will help sniff it out. What I am after is a dashboard that I can pull up when someone is suspected of overemployment because of a performance issue. In other words, a teammate complains they are very slow, or missing meetings; then I pullup my dashboard and see - yes, in fact it looks like they only spend 3-4 hours per day on corp infrastructure, time for a chat. The chat goes a little something like this "Some of your coworkers have raised concerns about your performance... what do you think is going on?".
I would not like to debate the merits of this being moral or not on either side, I want to focus on the tech we can employ to help move poor performers on from our company faster in order to keep the high performers motivated. If you are a high performer and working multiple jobs under our roof, we really have no issue, please just disclose that so we know it's not a competitor.
If they're capable of "overwork" why aren't the rest of us?
Start the crackdown at the top. Audit your C-Suite, go through their financials, track their minute-by-minute productivity, and ask them to report any external earnings.
See how they like being tracked and treated like fraudsters.
Once you've successfully tried out these techniques on them, move down to the senior managers.
Wonder why there don't seem to be startups seeking to profit from finding and eliminating employer side fraud, wage theft and the like?
Depending on the role, this is a poor metric. I'm saying this as someone who investigates this sort of behavior for a living.
Even a developer-- surely they're actively on the computer all day, right? Except extended whiteboard time, meetings, huddles, etc. all reduce that visible footprint.
> What I am after is a dashboard that I can pull up when someone is suspected of overemployment because of a performance issue.
You have the right approach-- what I'm about to share are a few queries I use to collect intelligence--not evidence--of such behavior. The two are very much not the same.
If you have Defender ATP (or maybe Sentinel?) you could look at this from a few angles. My own little trade secret is looking at the intersection of labor law and login counts.
Start with mouse jigglers. This query catches USB hardware jigglers that have become popular on Amazon and AliExpress. The best jiggler is an optical mouse on the face of an analog clock-- impossible to detect without cursor tracking.
Exceptions: This works for now, but don't trust it long-term since it's easy to spoof the IDs once vendors/users catch on.
``` DeviceEvents | extend ClassName = parse_json(AdditionalFields).ClassName | extend VendorIds = parse_json(AdditionalFields).VendorIds | extend DeviceDescription = tostring(parse_json(AdditionalFields).DeviceDescription) | mv-expand VendorIds | where VendorIds contains '\\vid_' and VendorIds contains '&pid_' | where VendorIds !contains '&rev_' and VendorIds !contains "&mi_" | where VendorIds contains "vid_0e90" | where Timestamp >= ago(90d) | where ActionType startswith "pnp" | summarize min(Timestamp), max(Timestamp), count(VendorIds) by DeviceId, DeviceName, tostring(ClassName), tostring(VendorIds), DeviceDescription ```
There are software mouse jigglers too, same caveat as above, and I'm sure there's a million more I don't know about but this one is currently yielding 300+ results for me as-is:
``` DeviceProcessEvents | where FileName contains "jiggle" or (FileName contains "mouse" and FileName contains "move") or FileName contains "caffeine" or FileName contains "amphetamine" | where Timestamp >= ago(90d) | summarize by DeviceId, DeviceName, FileName, ProcessCommandLine, InitiatingProcessAccountName ```
Then you want to look at login counts. My nutshell theory is that labor law mandates employees take 2-3 breaks a day, and per policy (and PCI and NIST and others) employees are supposed to be locking their workstation or seeing it lock itself every time they leave their desk. Ergo, we should see 4-5 logins at a minimum per employee per day (once in morning, once at lunch, and 2-3+ breaks later). WFH is no excuse to not lock the workstation.
Exceptions: You'll come across engineers who eat nothing but Adderall and piss in bottles at their desk. You'll also come across clowns who claim that they're RDPing into their work machine from a personal device; this is verifiable with a separate query but IME these people are usually problematic for other reasons and the RDP excuse is a red flag for OE in itself ("...b-b-but my big screen" is the usual counter). For some reason our network admin's account has 1 login in the last 90 days but I know for a fact he's working; I assume he's using a root account I don't know about on some jumpbox that I can't reach. You'll usually find executives topping the list of lowest login count for reasons other posters have enumerated. Be aware that this will also net people on leave, vacation, holidays, extended illness, etc.
``` DeviceLogonEvents | where LogonType == "Interactive" | where ActionType contains "Success" | where AccountName !contains "$" and AccountName !contains "-" and AccountName != "" | where Timestamp >= ago(90d) | summarize count(ReportId) by AccountName | order by count_ReportId asc ```
Use yourself as a baseline; you'll probably have hundreds of logins while working a varied schedule with a reasonable amount of AFK time. If your own normal working behavior has a score of n, anybody