Powershell - Who activated a User - powershell

I'm a beginner in Powershell and I would like to create a script to check who activated a specific user in our AD.
So far, I have this:
Get-EventLog -LogName Security -ComputerName ad.root| Where-Object {$_.EventID -eq 4722} | Select-Object -Property *
First of all, is this right? It checks all the activated users in the ad.root domain.
Second...How can I search for a specific user a display it?
I tried the select-object parameter, but it don't work.

4722 is the right event to search for. But I advise to use get-winevent instead of get-eventlog. By doing so you have the far better filter options (xpath) and it is faster.
But first you must ensure that those events are being logged. In the GPO valid to Domain Controllers ensure that the following option is active:
Advanced Audit Policy Configuration -> Account Management -> Audit User Account Management = Success
Furthermore as Mathias already has pointed out you need to check the logs of all Domain Controllers. You can achieve this by forwarding the events to central store by using event log forwarding or by using a 3rd party product like splunk or elastic. But for sure you can also check for those events by only using PowerShell.
Back to your example, to filter the log for eventid 4722 for a specific user account by using get-eventlog:
$username = "user123"
get-eventlog -LogName security | ?{$_.eventid -eq 4722 -and $_.message -match $username}

Related

Determine if an account is restricted to deny interactive login

Problem: Determine accounts with password does not expire across multiple environments, excluding accounts that can not be used to sign in interactively.
I am attempting to use powershell to generate a report that will show me account's who's passwords are set to never expire, however I want to exclude service accounts (accounts that have been restricted via GPO to only logon as service, similar process described in http://paulasitblog.blogspot.com/2017/01/deny-interactive-logon-for-service.html). I have found a few ways to pull this via powershell however it requires me to generate a list of servers, and run against accounts 1 at a time to see if they are restricted. Is there any switch that can be added to this that would be able to determine if an account has interactive logon disabled?
Current script I am using:
$b = $env:COMPUTERNAME
$c = Get-Date -Format "MM/dd/yyyy"
get-aduser -filter * -properties Name, PasswordNeverExpires |
where {$_.passwordNeverExpires -eq "true" } |
Select-Object DistinguishedName,Name,Enabled |
Export-csv Export-csv c:\Automation\$c-pw_never_expires-$b.csv -NoTypeInformation
The closest solutions I was able to find:
https://morgantechspace.com/2014/11/set-allow-log-on-locally-user-rights-via-powershell-cmd-csharp.html
Issue: This requires a 3rd party .dll, and I am unsure if this can be integrated to provide a single output.
https://www.powershellbros.com/get-user-rights-assignment-security-policy-settings/
This requires me to generate a server list, then run against the accounts to determine which accounts are limited.

Is there a way to find which user run what application on a server using Powershell

I am trying to find a way to find out who has ran an application (for example SQL) on a server, just to get some idea.
I tried Get-Process but this doesn't give me historic information, I want to get historical information
Get-Process -IncludeUserName *
what I want the return resule is "name of application", "user who ran it" and the last datetime it was ran by that user'
As for ...
I am trying to find a way to find out who has ran an application (for
example SQL) on a server, just to get some idea.
What you are asking for here is software metering.
SQL is a service that is always running once it is installed, so, no individual user is ever going to be running it. So, that is a bad example. MS Word for example would be a better example.
Yet there is nothing native in PowerShell that does this, software metering, but of course PowerShell can look at event logs. Yet if your auditing is not setup correctly then it's moot. This is better for a software metering tool, and there are several out there. So, why try and reinvent the wheel.
As for ...
I tried Get-Process but this doesn't give me historic information, I
want to get historical information
That is not what a process is nor what Get-Process is for. It, Get-Process only checks for and lists whatever process is currently running, regardless of what/who launched it.
As for...
what I want the return resule is "name of application", "user who ran
it" and the last datetime it was ran by that user'
As long as the process is running, you can get this, with that cmdlet.
However, what are you trying to accomplish by this?
Again, there are purpose built tools to meter software use.
https://learn.microsoft.com/en-us/sccm/apps/deploy-use/monitor-app-usage-with-software-metering
If you must go down this reinvent the wheel road, using scripting, then you need a task watcher on the target machines, which watches for the WinWord process to appear.
Get-Process -IncludeUserName |
Where ProcessName -EQ 'Winword'
... you then write those results to a file or database or your own event log each time you see that process.
Use PowerShell to Create and to Use a New Event Log
New-EventLog -LogName ScriptingGuys -Source scripts
When the command runs, no output appears to the Windows PowerShell console. To ensure the command actually created a new event log, I use
the Get-EventLog cmdlet with the –List parameter. Here is the command
and the associated output.
Write-EventLog -LogName ScriptingGuys -Source scripts -Message “Dude, it works … COOL!” -EventId 0 -EntryType information
Or just to a file
Get-Process -IncludeUserName |
Where ProcessName -EQ 'Winword' |
Select-Object -Property Name, StartTime, Username |
Export-Csv -Path 'F:\Temp\AppLaunchLog.csv' -Append
Import-Csv -Path 'F:\Temp\AppLaunchLog.csv'
# Results
Name StartTime UserName
---- --------- --------
WINWORD 5/23/2019 9:02:53 PM WS01\LabUser001

Powershell - last logged on user - same input, different output

UPDATE
# HAL9256
Your answer really made me think!
I did some more googling, and found this website which offers another approach
http://blogs.technet.com/b/heyscriptingguy/archive/2012/02/19/use-powershell-to-find-last-logon-times-for-virtual-workstations.aspx
So far, it works!
I remote into another server to run a powershell script that displays the last logged on user.
Several things
It only works when I run it in the context of a service account, not
the Administrator
It takes several minutes to output
But when I run it in the contenxt of a service account, I get different output for the same input
$line_array = #()
$multi_array = #()
[hashtable]$my_hash = #{}
foreach ($i in $args){
$line_array+= $i.split(" ")
}
foreach ($j in $line_array){
$multi_array += ,#($j.split("="))
}
foreach ($k in $multi_array){
$my_hash.add($k[0],$k[1])
}
$Sender_IP = $my_hash.Get_Item("sender-ip")
$eventList = #()
Get-EventLog "Security" -computername $Sender_IP `
| Where -FilterScript {$_.EventID -eq 4624 -and $_.ReplacementStrings[4].Length -gt 10 -and $_.ReplacementStrings[5] -notlike "*$"} `
| Select-Object -First 2 `
| foreach-Object {
$row = "" | Select UserName, LoginTime
$row.UserName = $_.ReplacementStrings[5]
$row.LoginTime = $_.TimeGenerated
$eventList += $row
}
$userId = $eventList[0].UserName
$userId
For instance, I invoke the script on commandline with
script.ps1 "sender-ip=10.10.10.10"
The first time I run it, it outputs the user's Window's logon name
The second time I run the same script with same input, it outputs the same service account I used to run the powershell script with
And when I try to run same script with same input, I get the output of this same service account.
~~~~~~~
Next, I try to run the script with another IP address
First time I run the script it outputs the Window's logon name
Second time I run the script, it outputs that same service account from which the powershell script is running
~~~~~~~
This seems to be a pattern. First time script it run, it return correct input, second time it is run, it returns the service account.
Why is this happening?
How to make the script always return the correct output no matter how many times it is invoked?
How to troubleshoot this?
This is because of how your script gets the information about the last logged on user.
You are getting the last logged on user from the security event log. This logs everyone who "logs on" to the computer... including accesses by WMI, service accounts, etc.
What's happening is:
Before Script Runs
Contoso\User1 logs onto computer
EventID 4624 - Logon Success - Contoso\User1 is Logged
Run Script the First time
Script runs as Contoso\ServiceAccount
Script access computer Via WMI to pull Security Event Log
Security Event Log shows last logged on user was Contoso\User1
EventID 4624 - Logon Success - Contoso\ServiceAccount is Logged
EventID 4634 - Logoff Success - Contoso\ServiceAccount is Logged
Run Script the Second time
Script runs as Contoso\ServiceAccount
Script access computer Via WMI to pull Security Event Log
Security Event Log shows last logged on user was Contoso\ServiceAccount
EventID 4624 - Logon Success - Contoso\ServiceAccount is Logged
EventID 4634 - Logoff Success - Contoso\ServiceAccount is Logged
This is because in order to access WMI, you have to authenticate on the computer. Essentially, WMI uses your service account to "log onto" the computer, access the information that it needs, returns the information, and logs off.
This is why you are getting the weird results.
To fix this, you have 3 options:
1.Continue to use the same script to pull out the event log entries. Add code to Filter out the service account name. i.e. use this to get the username:
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
Then use the "Where -FilterScript" to filter out the user that the script is running as.
The only downside to this method, is that there could be a lot of other service accounts that are running various scheduled tasks, or startup scripts that could change who the "last" logged on user was. It may be better to pull the last 5 logged on users, and then you would have a better idea of what's going on.
2.Use this code to get the currently logged on user:
(gwmi -class win32_computerSystem -computer "ComputerName").username
3.A different and unique way of getting the last logged on user is to use the last write access time on the user profile file (ntuser.dat). Typically only a user logging in "Interactively" will get have a user profile created.
(Get-ChildItem C:\users\*\ntuser.dat -Force | select #{e={(Split-path $_.Directory -Leaf)}},last* | sort lastwritetime -Descending

Measure 'Idle' time between CTRL-ALT-DEL and user typing in password and loging on -Windows 7

Windows 7 has the built in 'Boot Performance Diagnostics' and judging by the numerous reboots i've done, it does generate every now and then a detailed log on the user's login process and possible slowness.
That is not good enough for what I'm after though.
I want to measure EVERY Boot on a given machine.
There is little information however available on how to force it, except fiddling with registry keys that are System Protected so you don't tamper with them.
Some of the information can be found in the eventlogs so i switched to tracing the eventid 12
$yesterday = (get-date) - (New-TimeSpan -day 2)
$startuplog= Get-WinEvent -FilterHashTable #{LogName='System'; ID=12;
StartTime=$yesterday} -ErrorAction SilentlyContinue
But does anyone know how one can measure when the system was ready (ctrl-alt-del) and when the user hit the enter button after typing in the password? Is there a flag that can be set to raise such an event in a (diagnostics) event log?
You can compare the power state timestamp to the "Last Interactive Logon" feature of AD DS. That feature requires a domain functional level (DFF) of Windows Server 2008 r2 to work and workstation infrastructure of windows vista or later. The "msDS-LastSuccessfulInteractiveLogonTime" attribute is what you want. It's the time stamp of the last successful interactive logon (ctrl+alt+del).
To enable Last Interactive Logon on your domain:
http://technet.microsoft.com/en-us/library/dd446680(v=ws.10).aspx
Command to query attribute:
$Computer = 'hostname'
Get-ADComputer -Filter "name -eq $Computer" -Properties * | Select msDS-LastSuccessfulInteractiveLogonTime
P.S. Try to get away from using "-ErrorAction". In it's place, use Try/Catch/Finally code blocks.
http://blogs.technet.com/b/heyscriptingguy/archive/2010/03/11/hey-scripting-guy-march-11-2010.aspx

check for last number of users logged in to machine?

I'm trying to come up with a powershell script thatcan determine the last number of users that logged on to a machine. I'm stuck on to how to approach it. If I'm correct, using a get-wmiobject call will only get the last user. I'm wondering if maybe there is a call I can do to get the history of something like the user folder and get the last users that modified that?Or is there some simpler way?
http://social.technet.microsoft.com/Forums/en/winserverpowershell/thread/c61dc944-6c40-4ab8-93f8-8c345c37b0d4
Basically, all user logins are saved in the security log of each windows server. These are set in the log with the following eventIDs: 528 and 540. These two IDs are for a direct or a remote login to a machine. For my specific need, I have to following line in my script. If you have a similar need, be sure to read up on windows eventIDs on a site like this one
Get-EventLog -logname security -ComputerName $svr -Newest 100 | where {$_.eventID -eq 528
-or 540} | select time,user
enjoy!