Chapter 1. Getting Started

What Is Security?

To have a meaningful discussion of security in Windows Server 2003, we should first establish what security is. A dictionary definition might refer to security as “measures adopted to provide safety.” For the purposes of this book, that definition will work very well.

Computer security is not normally defined as a state of complete safety. Rather, it is defined as the collection of protective measures (including technology-based and nontechnology-based measures) that provide a defined level of safety. When security is mentioned throughout the book, you should keep this definition in mind. Security is neither a single protective measure nor complete protection against all attacks. It is a set of measures that provide the desired level of protection.

Many readers might say “I want complete security for my data against all attacks. Tell me how to do that.” The only solution that provides complete security is to put that data on a hard drive, incinerate the drive until it is completely turned to vapor, and then randomly mix the hard drive vapor with outside air until completely dissipated. Anything less is a compromise of security in the interest of another business factor such as usability, cost, or feasibility. The need for such compromises is a common theme throughout all computer security topics and is discussed in every chapter of this book.

Security Design in Windows Server 2003

The operating systems in the Windows NT line, which include Windows 2000 and Windows Server 2003, and even Windows XP, were designed from inception to facilitate security. All enforce user logon and ensure that all software runs within the context of an account, which can be restricted or permitted appropriately. Windows security is not limited to user logon-based security, but extends to all objects within the operating system. Files on the hard drive, entries in the registry, software components—all these elements have a security aspect based on the identity of the user or process accessing them. Operating system components can access objects only with the appropriate permissions and credentials. This can be both a benefit and a detriment.

Enforcing security restrictions on every component of the operating system can seem daunting. Access checks must occur when one Windows component talks to another. These include programs, device drivers, core operating system components, and so on—in short, everything. Setting appropriate security permissions is a task that requires detailed knowledge of the subject and the interaction between the components being configured. Misconfiguration of these permissions could cause undesirable behavior ranging in severity from a minor and easily fixed problem to a complete and irreversible loss of functionality.

The fact that this daunting security environment is part of the fundamental design of Windows Server 2003 is a big advantage. If strong and pervasive security is not designed into the core of an operating system (for example, consider Windows 95), it is nearly impossible to add it later. Developers and testers may find holes or make compromises when they patch security into an operating system. Legitimate components may already be designed to take advantage of the lack of security. The environment would necessarily be less secure than one designed for security from the beginning.

As a security administrator, you want to provide functionality and security to your users without burdening them or restricting them in a way that hinders their work. This is the mark of a great security administrator: the ability to successfully balance the security of proprietary and personal data and the usability of your systems in a way that maximizes the productivity of your organization. This book gives you many of the tools and techniques that enable you to do exactly that.

Approach to the Book

If you are familiar with the O’Reilly Cookbook format that is used in other popular books, such as the Active Directory Cookbook, Windows Server Cookbook, and Exchange Server Cookbook, then the layout of this book will not be anything new to you. The book is composed of 21 chapters, each containing 10–30 recipes for performing a specific security task. Within each recipe are four sections: Problem, Solution, Discussion, and See Also. The Problem section briefly describes the task the recipe focuses on. The Solution section contains step-by-step instructions on how to accomplish the task. The Discussion section contains detailed information about the problem or solution. The See Also section contains references to additional sources of information that can be useful if you still need more information after reading the discussion. The See Also section may reference other recipes, Microsoft Knowledge Base (MS KB) articles (http://support.microsoft.com/), Microsoft Developer Network (MSDN ) documentation (http://msdn.microsoft.com), or the Windows Server 2003 product documentation.

So Many Ways to Do It!

The O’Reilly Cookbooks embrace the notion that there are usually many approaches to accomplish any given task. You may be familiar with the famous Perl motto: There Is More Than One Way To Do It. With security tasks, there are often several different ways to do it. You can perform a task with a graphical user interface (GUI), such as MMC snap-ins and specialty management applications; you can use a command-line interface (CLI), such as certutil, net, netdom, or ldifde; you can configure settings directly in the Registry; you can use Group Policy to distribute and manage configuration changes; and, finally, you can perform the same task using a scripting language, such as VBScript or Perl. Whew!

Since people prefer different methods, and no one method is necessarily better than another, we decided to write solutions to the recipes using as many of these ways as possible. That means instead of just a single solution per recipe, we include several solutions. That said, some recipes cannot be accomplished with one of the methods or it is very difficult to do so. In that case, only the applicable methods are covered.

For Group Policy solutions, you can use the standard Group Policy Editor (GPE ) found in Windows Server 2003. We wrote the recipes assuming you’ve installed the Group Policy Management Console (GPMC ) that is highly recommended for all Group Policy management tasks. If you don’t have GPMC installed, you should download it from http://www.microsoft.com/windowsserver2003/gpmc and install it as soon as possible. It simplifies many of your Group Policy tasks and provides an excellent view into your system’s configuration.

Registry-based solutions are based on the format that the Regedit tool uses. This makes it easy for you to copy the format from the recipe. You can put the registry information we provide into a text file and save it as a .reg file. This file can then either be double-clicked to import the setting into the registry or you can use Registry Editor (regedit.exe) to import the data. Just click File and then click Import.

In the GUI and CLI solutions , we use standard tools that are readily accessible. There are other third-party tools that we could have used, which would have made some of the tasks easier to accomplish, but we wanted to make this book as useful as possible without requiring you to hunt down the tools we use.

We also took this approach with the programmatic solutions. We use VBScript for the programming language, primarily because it is widely used among Windows administrators and is the most straightforward from a code perspective when using Windows Management Instrumentation (WMI), Active Directory Service Interface (ADSI), and Windows Script Host (WSH). For those familiar with other languages, such as Visual Basic, Perl, and JScript, it is very easy to convert code from VBScript.

On the book’s web site, we’ve posted all of the Registry examples, VBScript code, and companion Perl solutions for every applicable recipe. Go to http://www.rallenhome.com/books/winsecckbk/code.html to download the code.

Where to Find the Tools

For the GUI and CLI solutions to mean much to you, you need access to the tools that are used in the examples. For this reason, in the majority of cases and unless otherwise noted, we only used tools that are part of the default operating system or available in the Resource Kit or Support Tools . The Windows 2000 Server Resource Kit and Windows Server 2003 Resource Kit are invaluable sources of information, along with providing numerous tools that aid administrators in their daily tasks. More information on the Resource Kits can be found at http://www.microsoft.com/windows/reskits/. The Microsoft Installer (MSI) for the Windows Support Tools can be found on a Windows 2000 Server or Windows Server 2003 CD in the \support\tools directory.

Security tools are often produced as single purpose tools that meet a specific need. This is usually the result of an individual getting upset that there is no built-in tool to perform the task. But frequently these single purpose tools are the result of shortcomings in the operating system, such as the account lockout tools we describe in Chapter 9. Whenever we use a one-off or specialty tool, the recipe will describe exactly where you can obtain it. We have intentionally limited the recipes to only use free tools (at the time of this writing). The exception to this is Windows itself—as of this writing, Windows is not free.

Once you have the tools at your disposal, there are a couple other issues to be aware of while trying to apply the solutions in your environment, which we’ll describe next.

Running Tools with Alternate Credentials

We strongly believe in supporting the principle of least privilege, which is the security tenet that a logged in user should only have permissions to do the required task at hand. In the Windows world, this means that everyone should log in using a regular user account and then use a separate administrator account that you grant elevated privileges only when necessary. This is beneficial because an administrator who wants to use elevated privileges has to log on with his administrative account explicitly instead of having the rights implicitly, which could lead to accidental changes in your environment. Assuming you employ this method, then you must provide alternate credentials when using administrative tools unless you log on to a computer, such as a domain controller, with the administrative credentials.

There are several options for specifying alternate credentials. Many GUI and CLI tools have an option to specify a user and password to authenticate with. If the tool you want to use does not have that option, you can use the runas command instead. The following command would run the enumprop command from the Resource Kit under the credentials of the administrator account in the rallencorp.com domain:

    > runas /user:administrator@rallencorp.com /netonly "enumprop \"LDAP://dc1/
    dc=rallencorp,dc=com\""

To run a Microsoft Management Console (MMC) console with alternate credentials, simply use mmc as the command to run from runas:

    > runas /user:administrator@rallencorp.com /netonly "mmc"

This will create an empty MMC console from which you can add consoles for any snap-ins that have been installed on the local computer. This is one of our favorite tricks because you can log on as a regular user and the MMC console is the only application running as administrator.

Tip

The /netonly switch is necessary if the user you are authenticating with does not have local logon rights on the machine you are running the command from.

There is another option for running MMC snap-ins with alternate credentials. Click on the Start menu and browse to the tool you want to open, hold down the Shift key, and then right-click on the tool. If you select Run As, you will be prompted to enter credentials to run the tool under.

Group Policy Notes

For all Group Policy solutions we use the standard Group Policy Editor (GPE ) found in Windows Server 2003. The policies are shown in a table format listing the location in GPE, the policy name, the setting, and, if applicable, where in your hierarchy you need to apply the policy (for example, at the domain level). Most of the policies here can be implemented as local policy simply by targeting the Group Policy Editor at the local computer instead of the domain.

We wrote the recipes assuming you’ve installed the Group Policy Management Console (GPMC). GPMC is a free add-on for Windows Server 2003 that simplifies Group Policy management in numerous ways. For example, GPMC allows you to list all policies in your domain in one location instead of hunting through sites, domains, and OUs for the policies. You can also create generic policies without linking them to any part of the hierarchy so you don’t affect users before you decide to implement them.

Programming Notes

With the VBScript solutions, our intention is to provide the answer in as few lines of code as is reasonable. Since this book is not a pure programming book, we did not want to overshadow the graphical and command-line solutions by providing pages of code or detailed explanations on how to use WSH, WMI, or ADSI. If you are looking for that, we recommend Part 3 of Active Directory, Second Edition (O’Reilly, 2003) or Windows 2000 Scripting Guide (Microsoft, 2003). The code in this book is meant to show you the basics for how a task can be automated and let you run with it. Most examples will take only some minor tweaking to make them do something useful in your environment.

To make the code as simple as possible, we had to remove error checking and other features that are standard scripting best practices. Next, we’ll describe how to incorporate these things into your own scripts so that you can quickly turn any code in this book into a robust script with all the trimmings.

Running Scripts Using Alternate Credentials

Just as you might need to run the graphical and command-line tools with alternate credentials , you may also need to run your scripts and programs with alternate credentials. One way is to use the runas utility when you invoke a script from the command line, or even use runas to open an administrative command prompt and launch other applications from there. Another option is to use the Scheduled Tasks service to run the script under credentials you specify when creating the scheduled task. And yet another option is to hardcode the credentials in the script. Obviously, the latter approach is not very appealing in many scenarios because you do not want the username and password contained in the script to be easily viewable by others. In addition to being insecure, it’s also a maintenance nightmare when those user credentials change. Nevertheless, at times it is a necessary evil, especially when working against multiple servers, and we’ll describe how it can be done with WMI, ADSI, and ADO.

WMI

Here is example WMI code that prints the list of disk drives on a system:

    strComputer = "."  ' localhost
    set objWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
    set objDisks = objWMI.InstancesOf("Win32_LogicalDisk")
    for each objDisk in objDisks
        Wscript.Echo "DeviceID: " &  objDisk.DeviceID
        Wscript.Echo "FileSystem: " &  objDisk.FileSystem
        Wscript.Echo "FreeSpace: " & objDisk.FreeSpace
        Wscript.Echo "Size: " & objDisk.Size
        WScript.Echo ""
    next

The following code does the same thing, except it targets a remote computer (srv01) and authenticates as the administrator account on that system:

    set objLocator = CreateObject("WbemScripting.SWbemLocator")
    set objWMI = objLocator.ConnectServer("srv01", "root\cimv2", _
                                          "srv01\administrator", "Adm1nPa33wd")
    set objDisks = objWMI.InstancesOf("Win32_LogicalDisk")
    for each objDisk in objDisks
        Wscript.Echo "DeviceID: " &  objDisk.DeviceID
        Wscript.Echo "FileSystem: " &  objDisk.FileSystem
        Wscript.Echo "FreeSpace: " & objDisk.FreeSpace
        Wscript.Echo "Size: " & objDisk.Size
        WScript.Echo ""
    next

To authenticate as an alternate user in WMI, you need to simply replace the GetObject call with two statements. The first is a call to CreateObject, which instantiates a SWbemLocator object. With this object you can then call the ConnectServer method and specify the credentials to authenticate with. The first parameter is the server name, the second is the WMI provider path, the third is the user, and the fourth is the user’s password.

ADSI

With ADSI, you can use the IADsOpenDSObject::OpenDSObject method to specify alternate credentials. For example, a solution to print out the description of a domain might look like the following:

    set objDomain = GetObject("LDAP://dc=rallencorp,dc=com")
    WScript.Echo "Description: " & objDomain.Get("description")

Using OpenDSObject, it takes only one additional statement to make the same code authenticate as the administrator account in the domain.

    set objLDAP = GetObject("LDAP:")
    set objDomain = objLDAP.OpenDSObject( _
        "LDAP://dc=rallencorp,dc=com", _
        "administrator@rallencorp.com", _
        "MyPassword", _
        0)
    WScript.Echo "Description: " & objDomain.Get("description")

ADO

It is just as easy to authenticate in ADO code as well. Take the following example, which queries all computer objects in the rallencorp.com domain:

    strBase    =  "<LDAP://dc=rallencorp,dc=com>;"
    strFilter  = "(&(objectclass=computer)(objectcategory=computer));"
    strAttrs   = "cn;"
    strScope   = "subtree"

    set objConn = CreateObject("ADODB.Connection")
    objConn.Provider = "ADsDSOObject"
    objConn.Open "Active Directory Provider"
    set objRS = objConn.Execute(strBase & strFilter & strAttrs & strScope)
    objRS.MoveFirst
    while Not objRS.EOF
        Wscript.Echo objRS.Fields(0).Value
        objRS.MoveNext
    wend

Now, by adding two lines (shown in bold), we can authenticate with the administrator account:

    strBaseDN  =  "<LDAP://dc=rallencorp,dc=com>;"
    strFilter  = "(&(objectclass=computer)(objectcategory=computer));"
    strAttrs   = "cn;"
    strScope   = "subtree"

    set objConn = CreateObject("ADODB.Connection")
    objConn.Provider = "ADsDSOObject"
    
    objConn.Properties("User ID")  = "administrator@rallencorp.com"
    objConn.Properties("Password") = "MyPassword"
    objConn.Open "Active Directory Provider"
    set objRS = objConn.Execute(strBaseDN & strFilter & strAttrs & strScope)
    objRS.MoveFirst
    while Not objRS.EOF
        Wscript.Echo objRS.Fields(0).Value
        objRS.MoveNext
    wend

To authenticate with ADO, you need to set the User ID and Password properties of the ADO connection object. We used the user principal name (UPN) of the administrator for the user ID in this example. Active Directory allows connections with a UPN (), NT 4.0 style account name (for example, RALLENCORP\Administrator), or distinguished name (for example, cn=administrator,cn=users,dc=rallencorp,dc=com) for the user ID.

Defining Variables and Error Checking

An important part of any script is error checking . Error checking allows your programs to gracefully identify any issues that arise during execution and take appropriate action. Another good practice when writing scripts is to define variables before you use them and clean them up after you are done with them. In this book, most of the programmatic solutions do not include any error checking, predefined variables, or variable cleanup. While admittedly this does not set a good example, if we included extensive error checking and variable management, it would have made this book considerably longer with little value to you, the reader.

Error checking with VBScript is pretty straightforward. At the beginning of the script include the following declaration:

    On Error Resume Next

This tells the script interpreter to continue even if errors occur. Without that declaration, any time an error is encountered the script will abort. When you use On Error Resume Next, you need to use the Err object to check for errors after any step where a fatal error could occur. The following example shows how to use the Err object.

    On Error Resume Next
    set objDomain = GetObject("LDAP://dc=rallencorp,dc=com")
    if Err.Number <> 0 then
       Wscript.Echo "An error occured getting the domain object: " & Err.Description
       Wscript.Quit
    end if

Two important properties of the Err object are Number, which if nonzero signifies an error, and Description, which will contain the error message (when present).

As far as variable management goes, it is always a good practice to include the following at the beginning of every script:

    Option Explicit

When this is used, every variable in the script must be declared or an exception will be generated when you attempt to run the script. This prevents a mistyped name from causing hard-to-trace errors. Variables are declared in VBScript using the Dim keyword. After you are done with a variable, it is a good practice to set it to Nothing so you release any resources bound to the variable, and don’t accidentally reuse the variable with its previous value.

The following code shows a complete example for printing the display name for a domain with error checking and variable management included:

    Option Explicit
    On Error Resume Next

    Dim objDomain
    set objDomain = GetObject("LDAP://cn=users,dc=rallencorp,dc=com")
    if Err.Number <> 0 then
       Wscript.Echo "An error occured getting the domain object: " & Err.Description
       Wscript.Quit
    end if

    Dim strDescr
    strDescr = objDomain.Get("description")
    if Err.Number <> 0 then
       Wscript.Echo "An error occured getting the description: " & Err.Description
       Wscript.Quit
    end if

    WScript.Echo "Description: " & strDescr

    set objDomain = Nothing
    set strDescr  = Nothing

Using Command-Line Options in a Script

Most code samples you’ll see in this book use hardcoded variables. That means when you want to change the value of a variable, you have to modify the script. A much more flexible solution is to obtain the desired value of those variables via command-line options . All good command-line programs work this way.

With WSH, you can retrieve the command-line options that are passed to a script by enumerating the WScript.Arguments object. Here is an example:

    set objArgs = WScript.Arguments
    WScript.Echo "Total number of arguments: " & WScript.Arguments.Count
    for each strArg in objArgs
        WScript.Echo strArg
    next

This script works, but there’s no structure to it. You can’t retrieve the value of the /foo option by name. You can only access elements of a WScript.Arguments collection by index number. To address this problem, WSH 5.6 introduced named and unnamed arguments. Let’s say we invoked the following command:

    > d:\scripts\dostuff.vbs /c:test /verbose:4

This bit of code shows how you can access the /c and /verbose options:

    WScript.Echo WScript.Arguments.Named.Item("c")
    WScript.Echo WScript.Arguments.Named.Item("verbose")

Writing the Output of a Script to a File

In most of the code in this book, we simply print the output to STDOUT using the WScript.Echo method. This is okay if you need an interactive script, but what if you want to schedule one to run periodically? Printing the output to STDOUT won’t do much good. An alternative is to write the output to a file instead. And this is pretty easy using WSH. The following code appends some text to a file:

    ' ------ SCRIPT CONFIGURATION ------
    strFile = "<FilePath>"   ' e.g. c:\output.txt
    ' ------ END CONFIGURATION ---------
    const ForAppending = 8
    set objFSO = CreateObject("Scripting.FileSystemObject")
    set objFile = objFSO.OpenTextFile(strFile, constForAppending, True)
    objFile.WriteLine("Script completed: " & Now)
    objFile.Close

There is nothing magical about this script. The Scripting.FileSystemObject interface is used for working with files. The OpenTextFile method supports different access options. The following script is a variation of the earlier script except it opens a file for writing (which will overwrite any existing data in the file) and writes out all of the running processes:

    ' ------ SCRIPT CONFIGURATION ------
    strFile = "<FilePath>"   ' e.g. c:\output.txt
    ' ------ END CONFIGURATION ---------
    constForWriting = 2
    set objFSO = CreateObject("Scripting.FileSystemObject")
    set objFile = objFSO.OpenTextFile(strFile, constForWriting, True)

    objFile.WriteLine("Script started: " & Now)
    objFile.WriteLine("List of processes:")

    set objWMI = GetObject("winmgmts:root\cimv2")
    for each objProcess in objWMI.InstancesOf("Win32_Process")
        objFile.WriteLine(vbTab & objProcess.Name)
    next

    objFile.WriteLine("Script completed: " & Now)
    objFile.Close

Instead of WScript.Echo, you have to use the WriteLine method of the Scripting.FileSystemObject object. If you also wanted to print the results to STDOUT, there is nothing to prevent you from putting a WScript.Echo statement right before or after a WriteLine statement.

Sending the Output of a Script in Email

When you automate a task, you are being proactive. Part of being proactive is trying to identify issues before they turn into major problems. If your scripts simply append their status to a log file, it is unlikely you’ll find out about any problems in a timely manner unless you are vigilantly watching over your log files. Fortunately, you can send emails very easily from VBScript so that instead of writing to a file, you can choose to send an email when there is a serious issue.

Here is an example script that just sends a simple email:

    ' This code sends an email via SMTP
    ' ------ SCRIPT CONFIGURATION ------
    strFrom = "script@rallencorp.com"
    strTo   = "rallen@rallencorp.com"
    strSub  = "Script Output"
    strBody = "The script ran successfully"
    strSMTP = "smtp.rallencorp.com"
    ' ------ END CONFIGURATION ---------

    set objEmail = CreateObject("CDO.Message")
    objEmail.From = strFrom
    objEmail.To = strTo
    objEmail.Subject = strSub
    objEmail.Textbody = strBody
    objEmail.Configuration.Fields.Item( _
             "http://schemas.microsoft.com/cdo/configuration/sendusing") = 2 objEmail.
             Configuration.Fields.Item( _
             "http://schemas.microsoft.com/cdo/configuration/smtpserver") = _
             strSMTP
    objEmail.Configuration.Fields.Update
    objEmail.Send
    WScript.Echo "Email sent"

This code requires the use of a SMTP-enabled mail server. The email is directed toward the mail server that relays it to the correct destination. This script also requires CDO to be installed on the client computer. This can be done by installing Outlook or by installing CDO separately from the Microsoft site (search for “CDO” on http://msdn.microsoft.com/).

Reading and Writing from Excel

A common question we see on newsgroups has to do with reading and writing Excel spreadsheets from scripts. Why would you want to do this, you might ask? Well, let’s suppose that we manage over 20 servers. We put together a small spreadsheet to keep track of them. Now, if we want to perform a task on all of our servers with a script, all we need to do is read information about each of the servers from the Excel spreadsheet and we don’t have to worry about hardcoding the servers within the script.

This next script shows how to iterate over the rows in a worksheet until the script comes across a row that does not have the first cell populated:

    ' ------ SCRIPT CONFIGURATION ------
    strExcelPath = "c:\data.xls"
    intStartRow = 2
    ' ------ END CONFIGURATION ---------
    On Error Resume Next
    set objExcel = CreateObject("Excel.Application")
    if Err.Number <> 0 then
      Wscript.Echo "Excel application not installed."
      Wscript.Quit
    end if
    On Error GoTo 0

    objExcel.WorkBooks.Open strExcelPath
    set objSheet = objExcel.ActiveWorkbook.Worksheets(1)

    intRow = intStartRow
    do while objSheet.Cells(intRow, 1).Value <> ""
      WScript.Echo "Row " & intRow
      WScript.Echo "Cell 1: " & objSheet.Cells(intRow, 1).Value
      WScript.Echo "Cell 2: " &  objSheet.Cells(intRow, 2).Value
      WScript.Echo "Cell 3: " &  objSheet.Cells(intRow, 3).Value
      WScript.Echo "Cell 4: " &  objSheet.Cells(intRow, 4).Value
      intRow = intRow + 1
      WScript.Echo
    loop

    objExcel.ActiveWorkbook.Close
    objExcel.Application.Quit
    Wscript.Echo "Done"

In this case, we just printed the values from the first four cells. You could obviously do more complex stuff with that information.

Now let’s say that we wanted to analyze the process information of a system. We could use the taskmgr.exe program, but it doesn’t really give us the flexibility we need. Instead we can write a script to output that information to a spreadsheet. Here is the code to do that:

    ' ------ SCRIPT CONFIGURATION ------
    strComputer = "."
    strExcelPath = "d:\procs.xls"
    ' ------ END CONFIGURATION ---------

    On Error Resume Next
    set objExcel = CreateObject("Excel.Application")
    if Err.Number <> 0 then
      Wscript.Echo "Excel application not installed."
      Wscript.Quit
    end if
    On Error GoTo 0

    ' Create a new workbook.
    objExcel.Workbooks.Add

    ' Bind to worksheet.
    Set objSheet = objExcel.ActiveWorkbook.Worksheets(1)
    objSheet.Name = "Processes"

    ' Populate spreadsheet cells with user attributes.
    objSheet.Cells(1, 1).Value = "Process Name"
    objSheet.Cells(1, 2).Value = "Command Line"
    objSheet.Cells(1, 3).Value = "PID"
    objSheet.Cells(1, 4).Value = "Owner"
    objSheet.Range("A1:D1").Font.Bold = True

    ' Query process information
    set objWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
    intProcessCount = 1
    for each objProcess in objWMI.InstancesOf("Win32_Process")
       ' For each process, write the name, command line options and process ID
       ' to the spreadsheet
       intProcessCount = intProcessCount + 1
       objSheet.Cells(intProcessCount,1).Value = objProcess.Name
       objSheet.Cells(intProcessCount,2).Value = ObjProcess.CommandLine
       objSheet.Cells(intProcessCount,3).Value = ObjProcess.ProcessID
       objProcess.GetOwner strUser,strDomain
       objSheet.Cells(intProcessCount,4).Value = strDomain & "\" & strUser
    next

    ' This formats the columns
    objExcel.Columns(1).ColumnWidth = 20
    objExcel.Columns(2).ColumnWidth = 50
    objExcel.Columns(3).ColumnWidth = 5
    objExcel.Columns(4).ColumnWidth = 30

    ' Save the spreadsheet, close the workbook and exit.
    objExcel.ActiveWorkbook.SaveAs strExcelPath
    objExcel.ActiveWorkbook.Close
    objExcel.Application.Quit

    WScript.Echo "Done"

We included comments in the code to help you follow along with what is happening. Pretty straightforward, isn’t it? Keep in mind that Excel must be installed on the computer in order to run this script.

Replaceable Text

This book is filled with examples. Every recipe consists of one or more examples that show how to accomplish a task. Most CLI- and VBScript-based solutions use parameters that are based on the computer, domain, forest, OU, user, etc., that is being added, modified, queried, and so on. Instead of using fictitious names, in most cases, we use replaceable text. This text should be easily recognizable because it is in italics and surrounded by angle brackets (<>). Instead of describing what each replaceable element represents every time we use it, we’ve included a list of some of the commonly used ones here:

<DomainDN>

Distinguished name of domain (e.g., dc=amer,dc=rallencorp,dc=com)

<DomainName>

Fully qualified DNS name of domain (e.g., amer.rallencorp.com)

<UserName>

SAM-style name for a user account (e.g., Administrator)

<UserDN>

Distinguished name of user (e.g., cn=administrator,cn=users,dc=rallencorp,dc=com)

<ComputerName>

Single label DNS hostname of computer (e.g., rallen-xp)

Reporting Security Issues to Microsoft

Microsoft wants to hear about your security issues. Specifically, they want to know if you’ve identified new vulnerabilities or issues with Windows products. Microsoft learns of new problems often from customers reporting issues. This gives Microsoft the opportunity to address them via patches, service packs, etc. before an attacker learns of that vulnerability.

The Microsoft Security Response Center (MSRC) was set up specifically to deal with such issues. The center maintains an open line of communications to listen for new security issues. If you feel you’ve found such an issue, you can contact the center directly at . The MSRC also maintains a web site at http://www.microsoft.com/security/msrc that describes how it works and what you can expect when you contact it.

Where to Find More Information

We hope that this book covers as many security recipes as you’ll need to get your job done. But security is nearly boundless. So many components have security integration that, in actuality, we’d have to provide a recipe for nearly every task in Windows to cover all the security-related tasks you can perform. In this book, we focused on the main Windows Server 2003 security topics and on security-sensitive technologies, such as Active Directory, DNS, and DHCP. Luckily, because Windows has been around so long and security is such a hot topic, there are plenty of other sources of information besides this book. This section contains some of the resources we use for security information.

Command-Line Tools

If you have any questions about the complete syntax or usage information for any of the command-line tools we use, you should first take a look at the help information for the tools. The vast majority of CLI tools provide syntax information by simply passing /? as a parameter. For example:

    > dsquery /?

Microsoft Knowledge Base

The Microsoft Support web site is a great source of information and is home of the Microsoft Knowledge Base (MS KB ) articles. Throughout this book, we include references to pertinent MS KB articles where you can find more information on the topic. You can find the complete text for a KB article by searching on the KB number at the following web site: http://support.microsoft.com/. You can also append the KB article number to the end of the following URL to go directly to the article: http://support.microsoft.com/?kbid=.

Microsoft Technet

Technet is the best resource for IT professionals that use Microsoft products in their environment. It contains a plethora of great security information as well as planning, deployment, and operations information for virtually every Microsoft product. Technet is available by subscription on CD or on the web at http://technet.microsoft.com/.

Microsoft Developers Network

MSDN contains a ton of information on the programmatic interfaces to Windows Server 2003. We sometimes reference MSDN pages in recipes. Unfortunately, there is no easy way to reference the exact page we’re talking about unless we provided the URL or navigation to the page, which would more than likely change by the time the book was printed. Instead we provide the name of the title of the page, which you can use to search on via the following website: http://msdn.microsoft.com/library/.

Web Sites

A variety of security-oriented web sites exist. We couldn’t possibly list them all here. We recommend you browse through the few that we recommend below and use Google searches to identify topics of interest on various web sites. Google searches usually help you find just the right information, regardless of web site.

Google search engine (http://www.google.com)

This now-ubiquitous search engine is a great starting place for any knowledge search on the Internet. It’s very fast and has indexes of almost all content available, including a great Microsoft index that often rivals Microsoft’s own search engine (http://www.google.com/microsoft).

Product documentation for Windows Server 2003 (http://www.microsoft.com/windowsserver2003/proddoc)

The old acronym RTFM holds up true even today. The product documentation (manual) is an often underrated resource. You’ll be surprised how many of your questions you can answer by just looking them up in the manual. This same content is available in the Help and Support Center, which is an icon on the Start menu.

Robbie Allen’s home page (http://www.rallenhome.com)

This is Robbie’s personal web site, which has information about the books he’s written (including this one). Robbie also provides links to the code contained in each of his books.

SysInternals (http://www.sysinternals.com)

This web site provides numerous free tools for Windows users and administrators. It also provides a wealth of information about how these tools work and, by proxy, how Windows works.

Newsgroups

If you have a question about a particular topic, newsgroups are a great place to start. A good tool to use for searching newsgroups is Google’s Groups search engine (http://groups.google.com). Just like its web search engine, the group search engine is very fast and is an invaluable resource when trying to locate information.

microsoft.public.security

This newsgroup is great for new security administrators and specialists alike. It’s a forum for general security questions and usually doesn’t delve into great technical depth. It’s also a good conversation-starting newsgroup.

microsoft.public.security.crypto

This is a very advanced technical newsgroup. Most of the conversations revolve around specific cryptographic practices and algorithms. PKI and EFS are extensively discussed here as is smart card technology. The true security eggheads monitor this newsgroup.

microsoft.public.windowsxp.security_admin

For more in-depth questions and discussions specifically around Windows XP and Windows Server 2003, this is the appropriate newsgroup. This one is often monitored by Microsoft and other security experts, and questions are usually answered pretty quickly.

Mailing Lists

Although they generate extra email that you need to go through, mailing lists are often the best way to stay current on security trends and issues. You usually get up-to-the-minute information on what’s happening and how to protect your network. Mailing lists are also much faster than newsgroups when you have a question, although newsgroups are more tolerant of “stupid” questions.

NTBugtraq (http://www.ntbugtraq.com)

This mailing list is an announcement platform for new bugs and security updates for Microsoft products. This list is often the fastest way you can find out about vulnerabilities (even before Microsoft, in many cases) and get early notice of Microsoft updates. There is also relatively little extraneous traffic on this list.

SecurityFocus (http://www.securityfocus.com/archive)

SecurityFocus hosts a number of security-oriented mailing lists. You can go to this single web site and subscribe to as many lists as you like. You can also click on the name of each list to view recent articles and get an idea of how many messages you can expect from each list.

Books

Our local bookstore has two entire racks of computer security books . Five years ago we would have been hard-pressed to find a single computer security book in any mainstream store. But with the availability of this useful information comes lots of useless books as well. We’ve spent more than our fair share of money buying security books that didn’t help. So here are a few recommendations on books that are well worth the money.

Active Directory Cookbook by Robbie Allen (O’Reilly)

Robbie’s book is chock full of Active Directory recipes, many of which apply to security tasks. If your security tasks are done in an AD environment, you’d be well served to take a look at this book.

Network Security: Private Communication in a Public World, Second Edition by Kaufman, Perlman, and Speciner (Prentice Hall)

Far and away the best book on fundamental security concepts. The authors do a fantastic job of teaching you security from the ground up while avoiding overly complex topics that could confuse you. This book is a must for the shelf of every security professional in the universe. If I (Mike) could buy a copy for everyone reading this paragraph, I would. Honestly.

Tip

In fact, if you see Mike speaking at a conference, ask him for a copy. He usually has one around and has been known to give them away.

Securing Windows Server 2003 by Mike Danseglio (O’Reilly)

This book covers the conceptual part that this cookbook does not cover in as much detail. Mike takes a scenario-based view of security and shows you how to solve whole problems from end to end. He also teaches you about fundamental security concepts and advanced applications. The book makes a great companion to this cookbook.

Magazines

Unfortunately the security community has few published magazines . There could be many reasons for that, but the most likely is that by the time a magazine gets published, the security landscape has changed and it’s somewhat useless. Instead, security articles are often thinly scattered among various magazines. We’re not recommending any of those magazines as the return of one or two security articles per issue just isn’t enough. There are few true security magazines.

2600: The Hacker Quarterly (http://www.2600.com)

This magazine has been around since 1984 and is still edited by Emmanuel Goldstein, its original editor. It is a pure hacker magazine, providing details on exploits, vulnerabilities, and current attack strategies. You can learn a great deal from studying your enemy’s strategy, and this magazine is it. Just be careful about subscribing to it at work with your corporate credit card—someone might get the wrong idea.

Windows Scripting Solutions (http://www.windowsitpro.com/WindowsScripting/)

This is a useful monthly newsletter that covers all aspects of scripting in the Windows environment. You’ll see a little bit of everything in this newsletter, including coverage of WMI, ADSI, and WSH techniques.

Security Administrator (http://www.windowsitpro.com/WindowsSecurityIndex.cfm)

This newsletter can help you stay abreast of the latest Windows security issues. Coverage includes everything from combating spyware and viruses to introducing new Microsoft security tools such as MBSA.

Get Windows Server 2003 Security Cookbook now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.