Executive Summary:

Security event logs contain important details about attempts to access the network and to modify accounts and Group Policy. Windows PowerShell makes accessing event logs easy, from both local and remote computers. Robert Sheldon introduces you to Windows PowerShell, walks you through the Security log access procedure for both local and remote computers, and shows you how to use PowerShell cmdlets to shape your scripting to get exactly the right log data the way you want it.


Security event logs can be vital instruments in an IT administrator’s security toolkit, providing the basic information to reveal attempted external and internal attacks, including invalid logon efforts, unauthorized file-access efforts, or account and Group Policy modifications. Regularly reviewing and analyzing these logs can help you discover and avert future network and asset intrusion. Windows PowerShell provides an easy means to access Security log information on local or remote computers. I’ll walk you through accessing Security event logs from both local computers and remote machines. Along the way, I’ll show you how you can use PowerShell cmdlets to get the exact data you’re looking for and sort and display it the way you want. Note that you’ll need to have Microsoft .NET Framework installed to use PowerShell. For a .NET download and other helpful PowerShell information sources, see the Learning Path box.

Retrieving Local Security Log Information
Accessing Security logs from a local computer requires procedures and scripting different from those required to retrieve information from a remote computer. On a local computer, the PowerShell Get-EventLog cmdlet is the primary command used to access system event logs, including Security event logs. You use Get-EventLog to retrieve information about an event log itself or to retrieve details about the events saved to that log. You can also expand the cmdlet to broaden the information returned. One of the parameters for Get-EventLog is -list. When you specify this parameter, as in the following statement, it returns a list of the event logs on the local system, as Figure 1 shows.

get-eventlog -list
You can see the Security log included in the list. This is the log we’ll use to access security event information.

When you use Get-EventLog to retrieve event information, you create a System.Diagnostics.EventLog object, and you can use any of the object's methods and properties within your PowerShell statements. One property you can use to return specific Security log information is LogDisplayName in a Where-Object subexpression. You pipe the Get-EventLog command results to a Where-Object command like this:

get-eventlog -list |<br>where \{$_.logdisplayname -eq `<br>"security"\}
The statement uses the where alias to refer to the Where-Object cmdlet, which creates a loop that repeats through the values returned through the pipeline. You then create a subexpression that specifies the results you want. The subexpression follows the alias and is enclosed in braces. In this case, the subexpression specifies that only Security log information should be returned.

Notice that the subexpression begins with the $_ symbol, a built-in variable that represents the current value in the pipeline or loop. A period and property name (.logdisplayname) follow the variable. As a result, only the property value logdisplayname is considered in the expression.

Next, the subexpression includes the -eq (equal) operator, followed by the string "security." This means the current logdisplayname value in the pipeline must equal “security.” As a result, the statement returns only Security log information. The back tick (`) at the end of the second line indicates that the command continues to the next line.

The preceding example retrieves only basic Security log information. However, you can retrieve additional information by piping the results to a Format-List cmdlet:

get-eventlog -list |<br>where \{$_.logdisplayname -eq `<br>"security"\} | fl *
The fl at the end of the pipeline refers to the Format-List command. The asterisk that follows the fl command indicates that all property information should be returned to the console.

While you’re getting used to working with the Get-EventLog cmdlet, you can use the following command to get more detailed information, examples, or Help information for Get-EventLog:

help get-eventlog -detailed
The statement uses the help built-in alias to refer to the Get-Help cmdlet. Now let’s find out how to access an object’s properties and methods.

Accessing Security Log Properties and Methods
To get more information about a specific object’s properties and methods, use the Get-Member cmdlet. To see a list of the Security log object methods and properties, pipe the Where-Object command results to a Get-Member cmdlet (using the gm alias), as in the following example:

get-eventlog -list |<br>where \{$_.logdisplayname -eq `<br>"security"\} | gm
Figure 2
shows the statement’s results, including the names of the available Security log objects, their member types, and definitions. Additional properties and methods are found further down the list.

Once you know the names of the available properties, you can retrieve their values. For example, this statement retrieves the value for the OverflowAction property:

(get-eventlog -list |<br>where \{$_.logdisplayname -eq `<br>"security"\}).overflowaction
Notice that the entire Get-EventLog statement is enclosed in parentheses, followed by a period and the property name. You must enclose the statement in parentheses so that PowerShell treats it as a single object. You can also save the statement to a variable, then call the variable and its property using the following code as an example:

$log = get-eventlog -list |<br>where \{$_.logdisplayname -eq `<br>"security"\}<br>$log.overflowaction
Make sure you exit the >> prompt by pressing Enter twice before typing "$log.overflowaction." The value in this case is OverwriteOlder, which means Windows will overwrite older events as the log fills.

Retrieving Security Events
So far, you've seen how to retrieve only general Security log information. Most of the time, you’ll want to retrieve more detailed file-entry information. To obtain all file entries, simply specify “security” when you call the Get-EventLog cmdlet, like this:

get-eventlog security
If your Security log contains a lot of entries, the returned list could be cumbersome, particularly if you want to take further action. You can limit your results by using additional parameters. For example, the statement

get-eventlog security -newest 10
uses the -newest parameter to request only the 10 most recent entries, as Figure 3 shows.

Earlier I showed how using Get-EventLog to retrieve log information creates a System.Diagnostics.EventLog object. When you use Get-EventLog to retrieve information about the events themselves, you’re creating a System.Diagnostics.EventLogEntry object. Since you’re creating an object, you can use the Get-Member cmdlet in the following example to retrieve a list of properties and methods available to that object:

get-eventlog security | gm
Figure 4 shows some of the methods available to the example Get-EventLog security object.

Let’s look at some especially helpful properties and methods that the System.Diagnostics.EventLogEntry object supports. One such property is TimeWritten, which shows the exact time and date an event occurred. For example, the following statement uses TimeWritten to return a list of Security log entries for the past 24 hours:

$date = (get-date).adddays(-1)<br>get-eventlog security |<br>where \{$_.timewritten -gt $date\}
The first line of the statement defines the $date variable, which uses the Get-Date cmdlet to retrieve the current date and time. The Get-Date object supports the AddDays method. In this case, I set AddDays to -1 day. This puts me in the Security log at a time 24 hours earlier than the current date/time. I can then use the $date variable in my Get-EventLog statement.

The Get-EventLog cmdlet is piped to a Where-Object command. The Where-Object subexpression uses the -greater than (-gt) operator to compare the TimeWritten value with the $date value. If the TimeWritten value is greater than the $date value, the subexpression evaluates to true and the log entry is returned. As a result, any Security event log entries generated in the last 24 hours are returned.

In some cases, you might not want to return the entries to the console but instead save them to a file. The following statement pipes the output from the Where-Object command to an Out-File command:

$date = (get-date).adddays(-1)<br>get-eventlog security |<br>where \{$_.timewritten -gt $date\} |<br>out-file c:\security.txt
This statement results in a newly created C:\security.txt file containing all Security log entries from the last 24 hours. Now that you’ve learned how to retrieve Security event log information from a local computer, it’s time to learn how to retrieve Security log entries from a remote machine.

Retrieving Remote Security Log Information
The Get-EventLog cmdlet on the local system lets you use the -newest parameter to limit the number of rows returned. However, the Get-EventLog cmdlet doesn't support remote access. As a result, your only option is to retrieve the entire log and then process the events. This means that, even if you want to look at only the 10 newest events, you must still retrieve all the events. Thus, you should consider issues related to network traffic and system availability before retrieving remote events.

To access remote Security log information, create the System.Diagnostics.EventLog object like this:

new-object `<br>system.diagnostics.eventlog `<br>("security", "server02")
The statement begins with the New-Object cmdlet, followed by the object-type name (system.diagnostics.eventlog). When you specify this object, you must include the name of the event log (security) and the target computer (server02 in this example).

You can also pipe the results of a New-Object command to the Get-Member cmdlet to get a list of the new Security event log properties and methods by using the following code:

new-object `<br>system.diagnostics.eventlog `<br>("security", "server02") | gm
To use these properties and methods, enclose the statement in parentheses and add a period and the property or method name. For example, the following statement returns the Entries property:

(new-object `<br>system.diagnostics.eventlog `<br>("security", "server02")).entries
As the name suggests, the Entries property returns a list of all the log entries.

To limit the number of entries, pipe the results to a Select-Object command and specify the number of entries to return, like this:

(new-object `<br>system.diagnostics.eventlog `<br>("security", "server02")).entries |<br>select -last 10
The Select-Object cmdlet (referenced by the select alias) uses the -last parameter to return only the most recent 10 entries.

To further narrow your results, you can pipe the results of the New-Object command to a Where-Object command. For example, the following statements define the $date variable, then use the variable in a Where-Object subexpression:

$date = (get-date).adddays(-2)<br>(new-object `<br>system.diagnostics.eventlog `<br>("security", "server02")).entries |<br>where \{$_.timewritten -gt $date\}
The above statement returns only those entries logged in the last 48 hours. As before, you can output these results to a file by using the following commands:

$date = (get-date).adddays(-2)<br>(new-object `<br>system.diagnostics.eventlog `<br>("security", "server02")).entries |<br>where \{$_.timewritten -gt $date\} |<br>out-file c:\security.txt
As these last two examples show, you can use the object’s methods to take specific actions. For example, the following statement uses the clear method to remove all entries from the log:

(new-object `<br>system.diagnostics.eventlog `<br>("security", "server02")).clear()
Only the Beginning
You should now have a good foundation for accessing Security event logs on local and remote computers and be able to retrieve any log information you need. However, the examples provided here are only a beginning. Investing more time in PowerShell and in reviewing Security event logs should pay off in fewer attacks and fewer account- and policy-modification attempts