Monday, March 21, 2011

PowerShell example for LdapSessionOptions.VerifyServerCertificate

 

I’ve started switching most of my management scripts over to PowerShell.  I previously had written a small C# command-line tool that would display the certificate expiration date of a Domain Controller’s LDAPS certificate.  This utility was based on Joe Kaplan’s sample.  As this utility was called as part of a much larger and more complex VBScript it only made sense to incorporate this functionality directly into PowerShell as well.  However, figuring out how to get PowerShell to deal with the VerifyServerCertificateCallback object was a more complex an undertaking than I had anticipated, and there were several times I almost gave up and kept the certificate date check as an external utility.  However, I did eventually figure it out and thought I’d share since there are no specific examples anywhere and few examples about PowerShell and callbacks in general.

Within the .NET Framework, System.DirectoryServices.Protocols provides comparatively raw access to the LDAP APIs.  In Joe’s example, the VerifyServerCertificate property is assigned to a new VerifyServerCertificateCallback object, which itself is a function that returns either True or False based on whatever logic one wants to employ.

Most of the examples I found centered on web-server SSL certificates and ServerCertificateValidationCallback and were based on either C# which has no issues with callbacks, like Joe’s, or PowerShell v1 which had to do lots of unnatural things to use the callback.

It turns out there are two important items to know about callbacks and PowerShell v2.  First, callbacks are implemented as a scriptblock.  Second, access to the callback parameters are provided via the args array.

Add-Type -AssemblyName System.DirectoryServices.Protocols
$LDAPId = New-Object System.DirectoryServices.Protocols.LdapDirectoryIdentifier(($DC + ":636"), $true, $false)
$LDAPConnection = New-Object System.DirectoryServices.Protocols.LdapConnection($LDAPId)
$LDAPConnection.Credential = New-Object System.Net.NetworkCredential("", "")
$LDAPConnection.AuthType = [system.directoryservices.protocols.authtype]::anonymous
$LDAPConnection.SessionOptions.SecureSocketLayer = $true
$LDAPConnection.SessionOptions.VerifyServerCertificate = {
    $MyCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $args[1]
    $DCCertDate = $MyCert.NotAfter
    $true
}
Try {
    $LDAPConnection.Bind()
} Catch {
    $DCCertDate = "No Certificate Found"
}

During execution, when the Bind method is called, the scriptblock attached to the VerifyServerCertificate property is called.  The LdapConnection parameter for the VerifyServerCertificateCallback delegate is contained in args[0] and the X509Certificate in args[1].  In this particular example I use the callback certificate to create a new certificate object, store the expiration date and return true, which allows the connection to succeed.

Tuesday, May 25, 2010

Execute PowerShell Scripts with a Restricted Execution Policy

 

By default, PowerShell will default to an execution policy of Restricted.  Hopefully this is not a surprise to anyone.  However, it is possible to execute scripts under this policy.  Simply start the shell using the ExecutionPolicy parameter.

For example, in our server loads, we need to prompt for an administrative password during the post-install process.  Previously, in W2K3, we were able to use the ScriptPW object to mask the input.  The object no longer exists in W2K8, so a different solution was needed.  Powershell provides the Read-Host cmdlet, which includes the AsSecureString parameter.  Using that cmdlet, I created a simple script that would prompt for the password.

I then needed to run the script automatically, but didn’t want to change the default execution policy.  To solve this, one can specify a one-time execution policy when starting the shell.

powershell -ExecutionPolicy RemoteSigned –File c:\postinstall\password.ps1

Monday, April 12, 2010

Happy 10th PromoDay <widgets>.com

 

My forest[1] celebrated the ten-year anniversary of the initial promotion today.  We had upgraded from an NT4 multi-master configuration, so this was a new promotion to become the empty root.  The account domains were slowly upgraded over the next year.  Technically, the domain services as a whole are more than 10 years old, but the official NT4 dates are lost to the sands of time.

c:\>adfind -config -f name="Enterprise Configuration" whencreated -alldc

AdFind V01.40.00cpp Joe Richards (joe@joeware.net) February 2009

Using server: xxxx.xxxx.com:389
Directory: Windows Server 2003
Base DN: CN=Configuration,DC=xxxx,DC=com

dn:CN=Enterprise Configuration,CN=Partitions,CN=Configuration,DC=xxxx,DC=com
>whenCreated: 2000/04/12-19:25:22 Eastern Daylight Time

1 Objects returned

We held a party for it today, and even got a “PromoDay” cake.

cake_edited

 

[1] Not technically “my forest”.  It does belong to the widget company for which I work, and I didn’t even work for them 10 years ago, and had nothing to do with its creation.  joe was responsible for most of it [2].  These days there are 5 EAs with operational responsibility, and me with engineering responsibility who can likely continue to call it “ours”.

[2] There are a lot of good stories about the early days of our AD.  This event brought out a few of them from ensuring joe didn’t promote the forest as joe.com to the buddy builds that were delivered almost daily as we pushed the scalability limits of Windows 2000 beyond what Microsoft had yet seen, but they’re joe’s to tell, not mine.  Go read about them if you want.

Tuesday, January 19, 2010

User Account Control (UAC) and NSUpdate

At work, I run my Vista SP2 system as a standard user with UAC turned on.  For the most part, UAC doesn’t cause me any problems in my day-to-day duties, except for one item.  Our DNS infrastructure runs on a BIND variant.  As such, nsupdate.exe is a common command-line support tool.  Similar to most other remote service management tools, the tool has no local security requirements.  However, attempting to run nsupdate on Vista creates an elevation prompt.  Using Windows Explorer, one can verify the executable is marked with the UAC shield.

bindsoftware

However, only nsupdate.exe is marked – none of the other BIND tools are marked.  Additionally, I found that renaming the file to something like nsupdat2.exe caused UAC to no longer prompt for elevation.

It turns out, there’s logic in UAC for elevating based on filename, regardless of local security requirements.  This allows update installers to be elevated appropriately.  However, nsupdate.exe is an innocent victim of a flawed heuristic detection pattern, like a false-positive from an AV signature.

To prevent UAC from forcing elevation of a process that doesn’t require it, this automatic prompting due to Installer Detection, can be turned off.  http://technet.microsoft.com/en-us/library/cc709628(WS.10).aspx provides an overview of the feature and its possible configurations.  In local security policy, navigate to Local Policies, Security Options and set User Account Control: Detect application installations and prompt for elevation to Disabled.  When this policy is enabled, which is the default, any filename which contains “update” will trigger elevation.  When disabled, this detection is turned off, and attempting to use nsupdate.exe no longer causes an elevation prompt.  I see this as a much better solution than renaming the file.  Now I can use nsupdate.exe as a standard user.

Wednesday, October 21, 2009

Comment Spam from Paramount Defenses

For those of you who know joe, perhaps you remember his past comments on Sanjay and Paramount Defenses.

Earlier today I answered an Active Dir question about how to tell when a machine was domain-joined by pointing the poster to my previous write-up on the domain-join process.  To be able to get the URL for my response, I opened the topic on my blog, which showed me the comments that had been added.  Imagine my surprise when I see a comment from someone named JM from a month ago.  It start with “Thanks for sharing your insightful thoughts and suggestions - very cool and helpful indeed.” (you couldn’t write a more generic opening if you tried) and then launches into a four paragraph sales pitch for GF.

I’m sorry, but my blog is not a spot for Sanjay and his friends to try and peddle their wares when they don’t have the ability or skill to do it on their own without latching on to me via comment spam.

Here’s the screen-shot of their intrusion before I whacked it.

spam

Actions like this make it easy to see exactly what kind of company and product they really have.

Tuesday, September 29, 2009

Additional LDAPS Requirements from Vista/W2K8

We have an ADAM instance that is protected by an SSL cert (LDAPS), and load-balanced behind a Cisco hardware device.  As a standard offering, we receive an SSL cert and a DNS alias for our “website”[1].  The DNS entry is similar to the following, with our public-facing name as an alias to the load-balancer:

C:\>nslookup adam.ad.test
Server:  UnKnown
Address:  192.168.2.1

Non-authoritative answer:
Name:    adam.ciscogss.ad.test
Address:  192.168.8.21
Aliases:  adam.ad.test

The SSL cert is also issued with the public-facing name of adam.ad.test.

This configuration functioned perfectly, for a while.  Eventually, we started having a few new application begin migrating to Windows Server 2008[2].  About this same time I also switched over to a Vista-based laptop as part of a pilot program within IT.

Connecting to our ADAM instance from either of these platforms resulted in a failure.  But, connecting from XP or W2K3 continued to work flawlessly.



This was a highly unexpected failure.  I had no problems connecting to any SSL-protected website from Vista or W2K8.  Any of those websites had certs and DNS entries that would be identical to our own setup for ADAM.  If IE on Vista could connect to an https website whose name is an alias, why couldn’t LDP on Vista do the same?

It turns out, Microsoft decided to tighten-up the requirements just for creating LDAPS connections, starting from the Vista codebase.  The problem is the certificate name didn’t match the DNS response.  After getting a new SSL cert for the public-facing name that included the load-balancer name as a Subject Alternative Name (SAN), the connections from Vista and W2K8 started working.

So, if you ever run into the same situation, ADAM (or AD) must be protected with an SSL cert that matches all the names in the DNS resolution path.

[1] Since it was a standard hosting offering, it was a little tricky at first to get our hosting team to understand our requirement for hosting the SSL port on 636, rather than 443.

[2] Yes, my company can be a little slow at moving to new platforms.  We didn’t have anyone try and authenticate against the ADAM instance from Vista or W2K8 until about July 2009.

Computers in space

If you want a fun, interesting read about the early days of computing, and how the requirements for manned-spaceflight helped push the state-of-the-art, you can find an insightful essay at http://history.nasa.gov/computers/contents.html.

Wednesday, September 23, 2009

Update on Exchange 2010 and AdminSDHolder

The Microsoft Exchange Team recently blogged on the ACEs being applied by Exchange 2010, that I discussed previously.

“[A]s some have correctly pointed out, that enables an elevation of privilege scenario that is unacceptable in any environment.  Microsoft agrees with this assessment and concurs that Exchange 2010 cannot ship with the permissions assigned to the AdminSDHolder role that allow for Active Directory forest privilege elevation.”

It’s great to see, especially this close to the planned release, that Microsoft realized what a critical controls issue this would have been, and is correcting the problem.

Bravo!

Monday, August 24, 2009

Exchange 2010 RC1 and AdminSDHolder

 

This post discusses Release Candidate software which may or may not reflect the final shipping version.

With the recent release of Exchange 2010 RC1, I threw it into a new sandbox to see what its schema and Forest/Domain Prep steps were like.

A picture is worth a thousand words.

E2010_AdminSDHolder

After the PrepareAD steps have finished, AdminSDHolder has several new ACEs added to it.  I’ve highlighted the most inappropriate ACE: Write Property for member, granted to the new Exchange Windows Permissions group.  This makes it possible for an Exchange Organization Administrator to elevate themselves to Enterprise Administrator with two actions (left as a simple exercise to the reader).

AdminSDHolder exists to protect the critical security groups, such as Enterprise Admins, from inadvertent  or accidental tampering by periodically setting the ACEs on those objects to known good values.  Since those values were originally defined by the authors of the AD code, they probably know a thing or two about what values are needed to protect AD.  With the new ACE on AdminSDHolder, AD itself now dutifully ensures that the new Exchange group can manage group membership for the Enterprise Admins group (along with Domain Admins, Account Operators and all other groups that were supposed to be “protected”).

Beyond AdminSDHolder, PrepareAD also throws down identical ACEs on the domain head, including ACEs like Write DACL inherited to all objects.  But from a controls perspective, none are needed beyond the initial Write Property for member.

If your organization has any rules for separation of duties between Exchange Admins and Enterprise Admins, the ACEs introduced by Exchange 2010 RC1 make that very difficult to enforce, if not impossible.

Monday, June 29, 2009

Unencrypting GSS-API Encrypted Payloads

 

In an earlier post I lamented the fact that Netmon couldn’t automatically use a server’s own private key to be able to decode SSL packets.  When working on something else, I ran across this post that details how to disable LDAP encryption.  I don’t know if it disables the encryption for NetLogonr or not, but thought someone may find the procedure useful.