July 2006

You are currently browsing the monthly archive for July 2006.

Best Practices Analyzers

The Exchange Best Practices Analyzer (ExBPA) has been around for a while now, and is a very useful tool in making sure that your Exchange implementation is following recommended best practices from Microsoft for optimal performance, reliability, and scalability.  The ExBPA was recently updated to include the ability to check the overall Exchange topology for readiness to upgrade to Exchange Server 2007.  The Exchange team blog has full details on the new “Readiness Check” in this posting.

In addition, Microsoft has released the Internet Security and Acceleration (ISA) Server Best Practices Analyzer (IsaBPA), which is designed to do the same thing for ISA implementations.  Supporting both ISA 2004 and ISA 2006, IsaBPA helps make sure that the ISA deployment adheres to a set of best practices outlined by Microsoft, and identifies critical configuration errors or potential problems.  The IsaBPA can be downloaded from the Microsoft Download Center.

Also available for download are the SQL Server Best Practices Analyzer and the BizTalk Server Best Practices Analyzer.

Tags: , ,

Improving Windows Security

The article, titled “Five Ways to Get Vista’s Security Now,” discusses five options for getting the equivalent of Vista’s User Account Control (UAC) functionality on today’s Windows.  UAC is one of the most widely touted new security features in Windows Vista because it eliminates the security hole that is created by needing to log in with an administrative-level user account (many applications won’t run properly without administrative permissions).

There’s nothing new here in terms of uncovering functionality that most security-conscious users didn’t already know about; the options included the following:

  • Logging in as a limited user (not really an option because so many things stop working);
  • Using “Run As” to run applications like the web browser and/or e-mail client as a limited user;
  • Using Process Explorer to run applications in a limited security context (does not require a separate limited user account); and
  • Using an application that automates the process of running applications with limited permissions (the article suggests DropMyRights).

These are all good options (except for the first one), but it’s option number 5 that makes me chuckle:  Get a Mac.

The article has this to say about why getting a Mac and switching to Mac OS X is a good option:

If Vista’s UAC is a copy of Mac OS X’s approach, why not stare in the horse’s mouth?

Why not indeed?  The introduction of Intel-based Macs and the rise of near-native speed virtualization options such as Parallels Desktop make this quite viable.  In my opinion, it’s like having your cake and eating it, too.

Tags: , , ,

The problem first presented itself as latency in responses from the domain controllers (DCs) to the Exchange servers and Outlook clients, resulting in slow responses in the Outlook client, delays in receiving new e-mail messages, etc.  Upon closer inspection, we determined that the problem was excessive CPU utilization on the DCs.  As we examined the DCs more closely, we then determined that traffic from the customer’s UNIX servers were driving up the CPU usage on the DCs.

After a great deal of troubleshooting and a lengthy call to Quest Technical Support, it was determined that the key problem was the length of the LDAP queries that were being performed—some taking up to 3 or 4 seconds for a single query.  The underlying cause of this delay was thought to be the Active Directory attribute selected as the user login attribute.  In this case, the customer had selected UID (an attribute added by the VAS schema extension) as the user login attribute.  Unfortunately, UID is an attribute that is not indexed in Active Directory, and it is believed that this is the key problem in the delays of the queries and the excessive CPU utilization caused by the queries.  The fix is simply to index this attribute, a change that can be made relatively easily via the Schema Management snap-in.

<aside>The default user login attribute for VAS is the user principal name (UPN), which is an indexed attribute.  If the VAS installation is going to use a non-indexed attribute as the user login attribute, however, you could see the same kinds of excessive delays and CPU usage.</aside>

Before the customer puts this change (indexing the UID attribute) into production, we’re going to test the change in a development environment and try to see if this addresses some of the symptoms.  Once the results of the testing are available, I’ll post an update here.

UPDATE:  Testing in lab today with the customer showed a definite, marked, and quite noticeable improvement in query performance after indexing the uID attribute in Active Directory.  This improvement in performance was repeatable as well; when we removed the index for uID, the delays and increased CPU utilization returned immediately.  So, make sure the user logon attribute in your VAS deployments is indexed in Active Directory.

Tags: , , , ,

In the original article on how to make mass changes to Active Directory, we discussed the use of CSVDE to produce the original output from Active Directory, Log Parser to massage the information into LDIF format, and LDIFDE to import the changes back into Active Directory.  Based on some additional testing of this procedure, I made some changes to that article, and I wanted to include additional information here.

For ease of reference, I’ve arranged this article in the same way as the original article was arranged, and new information is included in each pertinent section.

Exporting the Data from Active Directory

The use of CSVDE to export data out of Active Directory is great—except when the object name includes a comma in the name.  Here’s why.

Suppose that all your users are listed in Active Directory as “Lastname, Firstname”, such as this:

Smith, John
Public, Joe
Normal, Jane

If these users were stored in the built-in Users container, using a tool such as DSQuery to output their distinguished name would produce these results:

“cn=Smith\, John,cn=Users,dc=example,dc=net”
“cn=Public\, Joe,cn=Users,dc=example,dc=net”
“cn=Normal\, Jane,cn=Users,dc=example,dc=net”

The use of the backslash here is to escape the following comma so that it is not treated as a field delimiter.  The double quotes are used because there is a space in the name.

Using CSVDE, however, produces these results:

“cn=Smith\, John,cn=Users,dc=example,dc=net”
“cn=Public\, Joe,cn=Users,dc=example,dc=net”
“cn=Normal\, Jane,cn=Users,dc=example,dc=net”

Note the double backslash.  This will cause problems when Log Parser is used to put this information into LDIF format.

To work around this problem, use AdFind instead of CSVDE.  (Note that you can’t use DSQuery here because DSQuery can’t output in CSV format.)  With AdFind, your output is back to normal, with only a single backslash.

(A change made to the original article also notes that we can leave the “header line” intact in the output, so that Log Parser has field names to attach to the data in the output.)

Manipulating the Data

As noted in the changes to the original article, if we leave the “header line” from the exported output in the file, then we don’t have to use generic field names in the template; instead, we can use friendly names such as dn or sAMAccountName.

Also, the command line for Log Parser was updated to show the correct input type (“-i:CSV” instead of “-i:TEXTLINE”).  In addition, note the extra “-q:ON” and “-stats:OFF” switches, to reduce the extra output from Log Parser and remove the need to edit the file manually before importing it back into Active Directory.

Importing the Data Back Into Active Directory

There are no major changes in this section.  Only note that in multi-domain environments, it may be necessary to specify a specific domain controller (using the “-s” switch) and provide alternate credentials (using the “-b” switch).

Tags: ,

Josh Bates

It’s a really good CD, actually, and I’m particularly enjoying a couple of the tracks.  He’s got a great voice, and the music and lyrics are good.  So far, the title track (“Perfect Day”) is a favorite of mine, and I’m also enjoying “Alive” and “You Say Come.”  “King of Glory” is another great song, and I believe that it’s a hit single on the charts right now.

When you’re feeling down, or feeling like you aren’t quite “good enough”, then the track “Less” will certainly speak to your heart, and remind you of the unfailing love of God.

Overall, I’d recommend the album; it’s not too hard, but certainly not light listening either.  Sorry, I’m not a professional music reviewer, so I can’t really tell you any more than that.  Give it a try and see.

(Josh’s web site isn’t too bad, either, although I’m not a big fan of all-Flash sites.) 

Tags: , ,

Listing Groups in Active Directory

There’s nothing really unusual or new about the commands we’ll use to perform this task, other than the little tidbit about how to search for specific types of groups; I disclosed that information while discussing how to enumerate membership in universal groups.

As mentioned in that earlier article, the specific information on the values of the “groupType” attribute are fully documented here.  Using the values listed there, we sum up the values for the type of group we’d like to find and then place that into a “Dsquery *” command.  Some examples are listed below.

Finding global security groups:

dsquery * “dc=example,dc=net” -scope subtree
-filter “(&(objectCategory=group)(groupType=-2147483646))”
-limit 0

Finding domain local security groups:

dsquery * “dc=example,dc=net” -scope subtree
-filter “(&(objectCategory=group)(groupType=-2147483644))”
-limit 0

Finding universal security groups:

dsquery * “dc=example,dc=net” -scope subtree
-filter “(&(objectCategory=group)(groupType=-2147483640))”
-limit 0

Note that the base DN (the “dc=example,dc=net” in our samples above) only needs to be enclosed in quotes if there are spaces in the DN; otherwise, it can specified bare (without quotes) on the command line.  The LDAP filter, however, must always be enclosed in quotes.

Of course, you could easily take the output from these commands and pipe them to another command (like “dsget group” to enumerate membership) or redirect the output to a text file (using “> somefile.txt” at the end of the command) for future use.

UPDATE:  I forgot to provide details on how to list distribution groups; the examples above only list security groups.  Obviously, most of the query stays the same, and the groupType value changes for each distribution group scope:

Domain local distribution group:  groupType=4
Global distribution group:  groupType=2
Universal distribution group:  groupType=8

Substitute these values in one of the full queries above to list distribution groups of the specified scope.

Tags: , ,

Monitoring Event Logs with Log Parser

If you haven’t yet downloaded Log Parser 2.2 (the current version), you can get it from Microsoft’s download site.

As I’ve mentioned before, Log Parser is an extraordinarily versatile tool, and the functionality we’ve seen so far only scratches the surface.  In this next example of using Log Parser, we’re going to take advantage of the fact that Log Parser possesses the ability to natively parse Windows’ event logs.  That ability, combined with some SQL query syntax and command-line tricks, will give us an automated method for retrieving warning and error events from a user-defined list of servers and event logs.

Rather than belaboring the Log Parser syntax here, I’ll direct you to the Unofficial Log Parser support site.  There are numerous resources, both hosted there and linked to from there, that will help you understand the specific syntax.  Instead, let’s look at the full command and reverse engineer it to understand what’s happening.

The full command looks like this:

for /f “tokens=1,2 delims=,” %1 in (c:\servers.txt) do
@logparser -i:EVT “SELECT TimeGenerated,EventID,EventType,
EventTypeName,EventCategory,EventCategoryName,SourceName,
Strings,ComputerName,SID,Message FROM \%1\%2 WHERE
TimeGenerated > TO_TIMESTAMP(SUB(TO_INT(SYSTEM_TIMESTAMP()),86400))
AND EventType IN (1;2) ORDER BY TimeGenerated DESC” -o:CSV
-q:ON -stats:OFF >> c:\24hr-events.csv

Whew!  That’s a monster of a command.  Let’s break it down.

  1. First, we have the ever-useful “for /f” trick, which here is pulling two parameters from a file called “c:\servers.txt”.  Obviously, the path and name of the file are irrelevant; just be sure to put the correct path and name in the command.  The contents of this file should contain a list of servers and logs that will be checked by Log Parser, with a single server-event log pair on each line, separated by a comma.  So, to check the System log on SERVERA, SERVERB, and SERVERC, the file would look something like this:

    SERVERA,System
    SERVERB,System
    SERVERC,System

    Alternately, to review the Application log on SERVERA, the System log on SERVERB, and both Application and System on SERVERC, it would need to look like this:

    SERVERA,Application
    SERVERB,System
    SERVERC,Application
    SERVERC,System

    Simply place all the log names from all the servers you’d like monitored into this text file (in the appropriate format).

  2. Next, we have the Log Parser command itself.  This command specifies to use the Event log input format (“-i:EVT”) and uses a SQL SELECT statement to choose the specific fields from the event logs, filtering them by EventType (EventTypes 1 and 2 are Error events and Warning events) and by timestamp (only events in the preceding 24 hour period; refer to the Log Parser help file to try to decode the funky SQL math required to do that).  The rows returned by the query are sorted according to time, and the output is set to CSV (“-o:CSV”). The remaining options suppress other output (“-q:ON”) and suppress statistics (“-stats:OFF”).  Note the parameter substitution for the source of the query; here is where the server name and event log name will be substituted as they are pulled from the text file specified in the “for /f” clause.
  3. Finally, we redirect the output to a filename.  It’s important to use double redirection symbols here, or else the output file will contain only the results from the last server queried.

To make this command really helpful, though, we need a way to get the results of the Log Parser command into your hands, instead of making you go to a server and look at a text file.  This is where Blat comes in.

Blat is a command-line utility for sending SMTP messages.  With Blat, sending the output file from the Log Parser command above becomes as simple as this:

blat - -subject “Daily event log report”
-body “Here is the daily report of warning and error events
from the servers' event logs.” -to your@address -f source@address
-server your.mail.server -attacht c:\24hr-events.csv

Do you remember how to concatenate multiple commands on a single command line?  Use the double ampersands!  Using double ampersands, we can query the event logs and e-mail ourselves the results all on a single command line:

for /f “tokens=1,2 delims=,” %1 in (c:\servers.txt) do
@logparser -i:EVT “SELECT TimeGenerated,EventID,EventType,
EventTypeName,EventCategory,EventCategoryName,SourceName,
Strings,ComputerName,SID,Message FROM \%1\%2 WHERE
TimeGenerated > TO_TIMESTAMP(SUB(TO_INT(SYSTEM_TIMESTAMP()),86400))
AND EventType IN (1;2) ORDER BY TimeGenerated DESC” -o:CSV
-q:ON -stats:OFF >> c:\24hr-events.csv &&
blat - -subject “Daily event log report”
-body “Here is the daily report of warning and error events
from the servers' event logs.” -to your@address -f source@address
-server your.mail.server -attacht c:\24hr-events.csv

Voila!  You now have an automated command that will parse your servers’ event logs for warning and informational events, output those results into a CSV file (easily manipulated via your choice of spreadsheet program), and e-mail that CSV file to your e-mail address.  Can it get any easier?

Tags: , ,

GPMC Scripts

These scripts are mostly VBScript, with a couple JScript, and are (by default) found in the “Program Files\GPMC\Scripts” folder.  They are designed to be executed with the cscript.exe command-line script interpreter, and they all offer help via the “/?” parameter on the command line.

Here’s a quick look at three scripts that are (in my opinion) particularly useful:

  • FindGPOsByPolicyExtension.wsf:  This script finds all the GPOs that contain settings in a particular client-side extension (CSE), say “Software Installation.”  This is pretty helpful when you’ve inherited an existing GPO infrastructure and you have no idea how the existing GPOs play together.  With this script, you can easily find GPOs that contain overlapping settings.
  • FindUnlinkedGPOs.wsf:  This script, as the name implies, produces a list of GPOs that are defined but not linked to a scope of management (SoM, such as a domain, OU, or site).  Sure, you could do this in the graphical GPMC console, but when you’ve got a large number of SoMs and/or a large number of GPOs, that could take some time.  This script does the hard work for you.
  • ListSOMPolicyTree.wsf:  This script produces a textual listing of all the SoMs (scope of management, i.e., a domain, site, or OU) and the GPOs that are linked to each SoM.  This makes it easier to try to determine which GPOs are being applied to an object, and it’s handy to include this information in documentation.
  • GPOsWithNoSecurityFiltering.wsf:  Here’s another handy script.  This script finds GPOs that have no “Apply” permission to any security principals.  The GPOs are enabled, the GPOs are linked, but because they lack the “Apply” permission they won’t affect anyone or anything.

There are so many more scripts that I haven’t even touched on here that are equally useful for backing up GPOs, exporting GPOs, copying GPOs between domains, etc.

Keep in mind that you could easily schedule these scripts to run on a regular basis to help keep your documentation up to date and complete.

Visit this page for more complete details on all the scripts and their purpose.

Tags: ,

PowerPoint Zero-Day Exploit

The zero-day exploit takes advantage of a previous unknown vulnerability in PowerPoint to install a Trojan Horse application.  The vulnerability affects PowerPoint 2000, 2002, and 2003 running on various flavors of Microsoft Windows; it is unclear at this time whether Macintosh versions of Office are affected.  Based on what is known of exploit, it seems unlikely that Macs could be affected by the exploit, but that is not to say that the vulnerability doesn’t exist in the Mac versions of Office.  (Keep in mind that a vulnerability isn’t the same as an exploit.)

More information is available at the following links:

Simple filtering for PowerPoint files at the perimeter based on file extension is insufficient; Windows will open files in PowerPoint if they have a correct PowerPoint file header but an incorrect extension.  If your anti-virus vendor has released updates to check for infected/affected PowerPoint documents, be sure to install that update and vigorously check all incoming PowerPoint documents.

Now that Word, Excel, and PowerPoint have all had their zero-day exploits, which Office application is next?

Tags: , , , ,

Rather than using WMIC to do this (which is most likely possible), we’ll pull in a couple of third-party freeware tools.  First, we’ll use AdFind, by Joe Richards.  We certainly could have used Dsquery to provide the functionality we need, but this utility offers a bit more flexibility in the output options than Dsquery.  Next, we’ll team AdFind up with PsPasswd, part of PsTools suite by Sysinternals.

PsPasswd is a very flexible tool, capable of working on local or remote computers, multiple remote computers with their names specified on the command line, all computers within a domain, or remote computers specified by the contents of an input file.  It does not, however, support having the name of the remote computer piped into it from another command (at least, not that I could tell).  That doesn’t mean we can’t get our input for PsPasswd from another command, though.

Rather than using the old “for /f” trick, instead we’re going to redirect the output of one command into a text file, then read that text file into PsPasswd to change local user account passwords—all on a single command line.  We’ll use a pair of ampersands to instruct the second command to run only if the first command completes successfully.

Here’s what the command will look like:

adfind -b ou=Workstations,dc=example,dc=net
-f “(objectcategory=computer)” dNSHostName -list >
c:\temp\pclist.txt && pspasswd @c:\temp\pclist.txt
pcsupport HsaEAA2e! > c:\temp\audit.txt

In this example, we use AdFind to search the Workstations OU in the example.net AD domain for computers, and return each computer’s DNS host name in simple list format.  This output is placed into the file c:\temp\pclist.txt.  If this command is successful, then the PsPasswd command runs, reading the contents of that file and outputting the results into c:\temp\audit.txt for later review and storage.

Of course, this could easily be placed into a batch file and called with the OU as a parameter:

REM Accepts an Active Directory base DN as a parameter,
local account as a parameter, and new password as a parameter,
then changes the password on the specified account on all PCs in
the specified base DN.
REM
@echo off
adfind -b %1 -f “(objectcategory=computer)” dNSHostName
-list > %temp%\adfindtmp.txt && pspasswd
@%temp%\adfindtmp.txt %2 %3
del %temp%\adfindtmp.txt

It would be a good idea to incorporate some error checking, to ensure that the right number and type of parameters were specified, but I’ll leave that as an exercise to the readers.

There are a couple of problems with this approach.  First, it is assumed that all the PCs returned by the AdFind query will have the account specified on the command line; there is no functionality (not in this approach, at least) to specify the name of the account for each PC.  In a standardized environment this may not be a big deal.  Second, there is no way to determine if a computer returned by the query is actually up and running, so the PsPasswd command will attempt to operate even against PCs that may not be running or may not be reachable.  This will cause some errors and delays.

Even given these limitations, however, this is a very useful technique for managing local user accounts that are used for support purposes.

Tags: , ,

« Older entries