📜 ⬆️ ⬇️

PowerShell and Security Audit

PowerShell and Security Audit



Greetings to you! I want to share with you a way that can facilitate the routine work of the system administration of the Win system using PowerShell.
One fine day, I was faced with the task of daily tracking the activity of users who use a terminal server as workstations. I think I will express not only my opinion, saying that “Event Viewer” included in the Windows administration tools is not the most convenient means of tracking the situation on the server. Yes, there is a filter by which you can filter out only the events of interest to us, but there is no convenient way that changes the display format of this information. As a result, an idea appeared with the help of PowerShell to parse security log events.

To get the list of events we need the Get-EventLog command one of the parameters of which is the name of the log, in our case security.

image
')
The team displays the contents of the entire journal, which is not at all suited to me. But everything is not so bad, what you see in the screenshot is not just text, but quite objects, with the properties of which you can do anything within the capabilities of PowerShell. Get properties of these objects allows the Get-Member cmdlet. By running the command line Get-EventLog security | Get-Member Get-EventLog security | Get-Member , we will get a list of properties of all objects displayed by Get-EventLog.

image

By knowing the property list, you can manipulate the results of Get-EventLog. For example, to get a list of all events for today, the easiest way would be to use the parameters of the Get-EventLog cmdlet, namely the -after parameter. Full list of parameters can be found here . As a result, we get the command Get-EventLog security -after (Get-date -hour 0 -minute 0 -second 0) , where the Get-Date cmdlet Get-EventLog security -after (Get-date -hour 0 -minute 0 -second 0) current date and time, but the hour, minute, and second parameters set the time output from the beginning the current day. As a result, we will receive a list of events that occurred today. Already better, but still not that.
I need to get a list of all users logged into the server using the RPD protocol, which led me to study the EventID and EntryType values. Further I will give not the full list of these values.

EventID values

Each login event is supplemented with a specific input type, the list of which will be listed below.


EntryType Values



This information is drawn mainly from this source . From the obtained information, we can conclude that we need an event with EventID = 528 and EntryType = 10, which will correspond to the entrance to the computer via RDP. A little change our team.
Get-EventLog security -message "* :?10*" -after (Get-date -hour 0 -minute 0 -second 0) | ?{$_.eventid -eq 528 }

The -message parameter reflects the complete message of our event, which contains the “Entry type” (“Entry Type”, since I have the Russian version of 2003), through the templates we set the search for the line of interest.

Since I did not find the parameters of the Get_EventLog -EventID cmdlet, I had to use the properties of the object:
$_ means the object itself which appears initially
-eq means equality of value, in our case 528

The result will be the following:

image

In general, what is needed, but only that information is displayed to us. We will fix it. For me, three parameters of the object are relevant: time, username, IP address. In the future, we will create an object and enter the data of interest into it. I created the script “test.ps1”, because the whole team will be problematic to recruit.

$Events = Get-EventLog security -message "* :?10*" -after (get-date -hour 0 -minute 0 -second 0) | ?{$_.eventid -eq 528 }

$Data = New-Object System.Management.Automation.PSObject
$Data | Add-Member NoteProperty Time ($null)
$Data | Add-Member NoteProperty UserName ($null)
$Data | Add-Member NoteProperty Address ($null)

$Events | %{

$Data.time = $_.TimeGenerated

$message = $_.message.split("`n") | %{$_.trimstart()} | %{$_.trimend()}

$Data.UserName = ($message | ?{$_ -like ":*"} | %{$_ -replace "^.+:."} )
$Data.Address = ($message | ?{$_ -like " :*"} | %{$_ -replace "^.+:."})

$data

}


Let's sort this code closer.
$Events = Get-EventLog security -message "* :?10*" -after (get-date -hour 0 -minute 0 -second 0) | ?{$_.eventid -eq 528 } $Events = Get-EventLog security -message "* :?10*" -after (get-date -hour 0 -minute 0 -second 0) | ?{$_.eventid -eq 528 } - we put the results of the sample on the events in a variable, so that later it would be convenient to work with it.

Next, create a “pattern” of our future table containing three values: time, user name, and address.
$Data = New-Object System.Management.Automation.PSObject
$Data | Add-Member NoteProperty Time ($null)
$Data | Add-Member NoteProperty UserName ($null)
$Data | Add-Member NoteProperty Address ($null
$Data = New-Object System.Management.Automation.PSObject
$Data | Add-Member NoteProperty Time ($null)
$Data | Add-Member NoteProperty UserName ($null)
$Data | Add-Member NoteProperty Address ($null
)


$Events | %{} $Events | %{} - go through each object that will be in the selection results

$Data.time = $_.TimeGenerated - $Data.time = $_.TimeGenerated time
$message = $_.message.split("`n") | %{$_.trimstart()} | %{$_.trimend()} $message = $_.message.split("`n") | %{$_.trimstart()} | %{$_.trimend()} - put the array of strings in the message variable, which are separated by the line break ('n), the trimstart (), trimend () functions remove all extra characters at the end and the beginning of the line, the split function splits the line .
$Data.UserName = ($message | ?{$_ -like ":*"} | %{$_ -replace "^.+:."} )
$Data.Address = ($message | ?{$_ -like " :*"} | %{$_ -replace "^.+:."})
$Data.UserName = ($message | ?{$_ -like ":*"} | %{$_ -replace "^.+:."} )
$Data.Address = ($message | ?{$_ -like " :*"} | %{$_ -replace "^.+:."})
Next, in the newly formed array, we are looking for matches on the string " User: "and" Network address of the source: ", and -replace later removes these regular expressions, leaving the information itself.

Run the script with the command .\test.ps1 . (As you can see, to run the PS script, you have to specify the path, even if it is in the current working folder):
image

If the script does not start, then most likely your PoSh is not configured to run scripts. Run the Set-ExecutionPolicy RemoteSignet .

It looks quite good, but I think you can improve the script. For convenience, we will add to it the possibility of setting parameters, and highlighting lines with a color based on the IP address mask.

param ($key1,$val1,$val2,$val3,$val4,$val5,$val6)

if ($val1 -eq $null) {$val1=0};

$mydate = Get-date -hour 0 -minute 0 -second 0;

if ($key1 -eq "year") { $mydate = (Get-date -hour 0 -minute 0 -second 0 -day 1 -month 1); $mydate = $mydate.addyears(-$val1); };

if ($key1 -eq "month") { $mydate = (Get-date -hour 0 -minute 0 -second 0 -day 1); $mydate = $mydate.addmonths(-$val1); };

if ($key1 -eq "day") { $mydate = $mydate.adddays(-$val1) };

if ($key1 -eq "date") { $mydate = (Get-date -hour 0 -minute 0 -second 0 -day $val1 -month $val2 -year $val3); }; #

if ($val4 -eq $null) {$Events = Get-EventLog security -message "* :?10*" -after ($mydate) | ?{$_.eventid -eq 528 }}
if ($val4 -ne $null) {$Events = Get-EventLog security -message "* :?10*" -after ($mydate) -before (get-date -hour 0 -minute 0 -second 0 -day $val4 -month $val5 -year $val6) | ?{$_.eventid -eq 528 }}
$Data = New-Object System.Management.Automation.PSObject
$Data | Add-Member NoteProperty Time ($null)
$Data | Add-Member NoteProperty UserName ($null)
$Data | Add-Member NoteProperty Address ($null)

$Events | %{

$Data.time = $_.TimeGenerated

$message = $_.message.split("`n") | %{$_.trimstart()} | %{$_.trimend()}

$Data.UserName = ($message | ?{$_ -like ":*"} | %{$_ -replace "^.+:."} )
$Data.Address = ($message | ?{$_ -like " :*"} | %{$_ -replace "^.+:."})

$textcolor = $host.ui.rawui.foregroundcolor

$host.ui.rawui.foregroundcolor = "red"

if ($data.address -like "192.168.0*") {$host.ui.rawui.foregroundcolor = "DarkGreen"}
if ($data.address -like "10.*") {$host.ui.rawui.foregroundcolor = "yellow"}

$data

$host.ui.rawui.foregroundcolor = $textcolor

}


param ($key1,$val1,$val2,$val3,$val4,$val5,$val6) - defines the parameters passed to the script.

if ($key1 -eq "day") { $mydate = $mydate.adddays(-$val1) };; we check the passed parameters for compliance with the key, if the key is the same, then we adjust the date according to the specified parameters. In this case, the “day” key is passed as an argument by whose argument we will translate the date a certain number of days ago. Those. the log will be displayed for a certain number of days, the rest of the conditions are fulfilled by analogy, for a month and for a year. If the key “date” is indicated, then a specific date indicated by a space, for example, “01 05 2011”, is taken as a reference point, if we also specify another date after the space, then a certain period specified in these dates will be displayed on the screen. To display information in color, it was originally planned to use the Write-Host cmdlet, which has the parameters -backgroundcolor and -foregroundcolor, but eventually had to be discarded because it is not friendly with the output of objects.

image

I made the internal LAN display green, external yellow, and all other unknown addresses in red for clarity.

And if you specify {$_.eventid -eq 529 } then the result will be all login attempts with the wrong passwords.

image

The list is quite long, it is useful to check and block such villains on the firewall a couple of times a day.

As a result, the script, with minimal modifications, can be adapted to conveniently display any information contained in the Event Log.

Source: https://habr.com/ru/post/118644/


All Articles