Security is at the top of every systems administrator's priority list. A good security strategy involves combining a variety of methods to keep malicious intruders and processes (e.g., viruses, worms) at bay—all while remaining transparent to authenticated users. Aside from implementing an arsenal of technology to secure your networks, you also need to diligently monitor your security event logs for unauthorized-access attempts. Windows Server 2003 and Windows 2000 domain controllers (DCs) have made significant improvements in security-event auditing. Specifically, DCs add new event IDs to distinguish various security events that are, in Windows NT, simply categorized into one or two generic security-event entries.
How often have you taken calls from users asking why their account has become locked and claiming that they haven't yet tried to log on? If you follow sound security procedures, you determine where and how the user's account became locked before you unlock it because that locked account could be a sign of malicious activity on your network. I've found that the accounts of many desktop technicians get locked because they persistently use their own credentials at a user's desk to map a drive letter onto network shares and forget to disconnect afterward. If quickly determining the origin of the locked account were simple, the technician could correct the problem to prevent future lockups. I needed a way to quickly obtain all the failed logon attempts on my DCs without having to go to each one individually.
Enabling Account Logon Failure Auditing
Out of the box, a Windows 2003 or Win2K DC logs only successful account logons. Because we're interested in logging failed logons, we'll need to explicitly enable this functionality. You can do so through Group Policy, either individually on each DC or more appropriately in the Default Domain Controllers Policy. To accomplish the latter, open the Default Domain Controllers Policy and navigate to Computer Configuration, Windows Settings, Security Settings, Local Policies, Audit Policy, as Figure 1 shows. Change the Audit account logon events and Audit logon events so that the system logs both Success and Failure events. Close the policy to save it.
Event ID 675
Win2K introduced event ID 675, which Figure 2 shows, and Windows 2003 has carried it forward as the event ID for recording failed logon attempts using Kerberos. This event ID technically indicates a pre-authentication failure that can have a number of different causes. This event logs not only the username of the user who attempted the logon but also the failure code and the IP address of the computer that generated the event. If the user account locked up because of an invalid password at the user's workstation, this address should be the user's IP address. If it's a different address, you might want to look at it more closely, particularly if you're unable to resolve the IP address to a host in your domain. (Event ID 529 is another very common event ID for failed logon events. You can apply the same techniques presented in this article for monitoring those events or any other specific security event you might be interested in monitoring.)
A Script to Find Failed Logons
To achieve my objective, I wrote a Windows shell script—findfailedlogon.cmd—that uses Sysinternals' freeware tool PsLogList. This tool lets you access event-log information from the command line. For example, if you want the tool to display all event ID 675 security events from a DC called DC1 in comma-delimited format, you would use the command
psloglist \\DC1 -s -i 675 security
The -s switch specifies delimited output (with the default delimiter set to the comma character), and the -i 675 switch specifies that you want to include only events with event ID 675. The final parameter of the command is the name of the event log you want to query, which in this case is the Security event log. To find out more about what PsLogList can do, enter
The concept of findfailedlogon.cmd, which Listing 1 shows, is fairly simple. For each DC that the script specifies, the script parses the output of the Psloglist command against that server and combines it into one output file. Toward the beginning of the script, in the domaincontrollers variable, which appears at callout A, you'll see the DCs that the script will query. When the script is executed, it first outputs a header to the output file that labels each field. Then, for each DC, it executes the Psloglist command, extracting the event's date, timestamp, and description from the output, as you see in callout B.
The meat of the script comes in the parsing of the description field. As you saw in Figure 2, the username, failure code, and client address all reside in the event's description field. The script's parse section takes care of both parsing the description field and outputting the event details to the output file, as you see in callout C. To do so, it echoes the description text through a For loop to obtain the 5th, 14th, and 17th items in the description text (delimited by blank spaces). The 5th item is the username, the 14th item is the failure code, and the 17th item is the client address. Because the username and client address are already meaningful, they don't require any further work. But the failure code is a hexadecimal number that represents the reason for the failure. To make this number more meaningful, the script compares the failure code with a known set of failure codes and generates an error description. See Table 1 for a list of the known error codes that the script handles.
Finally, the script combines all this information in comma-delimited format and sends it to the output file. You can easily view the results in Microsoft Excel, in which you can filter and sort the date according to your needs.
Getting the Script to Work
I tested this script on Windows XP Service Pack 1 (SP1) and SP2, in a Windows 2003 Active Directory (AD) domain. To make the script work in your environment, follow these steps:
- Download PsLogList from Sysinternals (http://www.sysinternals.com/ntw2k/freeware/psloglist.shtml) and extract it to a local folder or network-accessible share.
- Edit the path in the pstoolspath variable within the script to the path where you have psloglist.exe.
- Enter the list of DCs you want this script to query in the domaincontrollers variable. Separate each computer name with a space.
- Run the script, using the syntax
where outputfile is the name of your output file. I suggest using the .csv filename extension for the output file name so that it automatically associates with Excel.
Regularly checking your Security event logs is crucial to ensuring network security and stability. Findfailed-logon.cmd script can help you validate user claims of locked accounts and can assist in the identification of possible security violations in your network. If you really want to get fancy, you could modify this script to email the output file by using Blat (http://www.blat.net) or a similar command-line email tool. You could then schedule the script to run on a daily basis, thereby ensuring a consistent reporting mechanism for detecting network logon failures.