Why Does It Say <Unknown Contact> When Viewing Network Share Permissions?

I only get to work with Active Directory trusts every so often. I think multi-domain forests seem to be falling out of fashion. At least for those of us who've heard of federation. Regardless, here's an interesting issue I ran into the other day:

So I have this domain, contoso.com.  In contoso.com, there is a one-way forest trust established with fabrikam.com, such that contoso.com trusts fabrikam.com.  This way, users in fabrikam.com can access resources in contoso.com.

On pc1.contoso.com, I create a network file share. I add permissions for my own user account, contoso\ryan, to it.  Then, I add permissions for fabrikam\steve to access the file share also.  The operation was successful and the file share appears to be set correctly.  However, when I go back and view the permissions for the file share again, it takes a very long time, as if it were waiting on something to time out, and then eventually, this is what I see:

File Share Permissions

So why is fabrikam\steve showing up as <Unknown Contact> when viewed from the contoso.com domain?  What we have here, is a SID translation failure.  But why?  First, a little background.  Here is what Microsoft says about users in your forest who are members of another forest:

"When a trust is established between a domain in a forest and a domain outside of that forest, security principals from the external domain can access resources in the internal domain. Active Directory creates a foreign security principal object in the internal domain to represent each security principal from the trusted external domain. These foreign security principals can become members of domain local groups in the internal domain. Directory objects for foreign security principals are created by Active Directory and should not be manually modified. You can view foreign security principal objects from Active Directory Users and Computers by enabling advanced features." [ Source ]

So if you go look in the ForeignSecurityPrincipals container in contoso.com, you'll see an object that represents the user account of fabrikam\steve, but his friendly name or samAccountName is not part of that record. It's just a SID.  When we pull up a permissions file dialog box like the one above, Windows attempts a SID to name translation... but it fails.  There's a little bit of technical documentation on how SID translation occurs:

"LSA on the computer that the call is sent to (using the LSA RPC interface) will resolve the SIDs it can map and send on the remaining unresolved SIDs to a domain controller in the primary domain. The domain controller will resolve additional SIDs to account names from the local database, including SIDs found in SidHistory on a global catalog.

If SIDs cannot be resolved there, the domain controller will send remaining SIDs to domain controllers in a trusted domain where the domain part of the SID matches the trust information." [ Source ]

There are many functions regarding SID lookups, and I don't know exactly which ones are used at each location, but the general concept is the same and you can see how this procedure could take a while to time out. And when it fails, you see <Unknown Contact>.  Or maybe just the unresolved SID of security principal.  Depends on which version of Windows you're using and exactly which dialog box you're looking at.

The reason it happens in our scenario is because of the one-way trust. Contoso.com cannot call upon fabrikam to translate SIDs from its forest, because fabrikam does not trust contoso.

To fix it, we could allow anonymous SID translation in fabrikam... but for many that is an unacceptable security risk.  Or we could make the trust two-way.  Or, if you're unable to do either of those things, you could at least create a security group in contoso, add the individuals from fabrikam to that group, and just assign the group to the network share ACL.  The functionality would be the same but at least you wouldn't have to look at "<Unknown Contact>" every time you opened that dialog box.

Mystery solved.

For more information on this, see the ServerFault question that I answered here, as well as the much better Ask the Directory Services team blog post here.

Examining Internet Explorer Tracking Protection Lists (with Powershell)

I know that Firefox and Chrome are still the only browsers that most people will ever even consider using, but ever since I started using Windows 8, I've not yet really felt a compelling reason to stop using the built-in IE10. It's fast, it passes Acid tests, and has a nice "Developer Mode" built-in where you can change IE and rendering versions on the fly (hit F12 on your keyboard.) That, and Compatibility Mode, which I think is really under-rated in a corporate environment, where employees are forced to use antiquated corporate websites that were built for IE5.

About the only thing I miss from Chrome is my sweet, sweet AdBlock. Does IE have anything that can compare? Well, it has Tracking Protection Lists, which is a good start:

IE Tracking Protection Lists

IE Tracking Protection Lists

The Personalized List kinda' sucks because you only have two choices - either block everything that IE detects as a Javascript-type thing that pulls info from other domains and is frequently seen in similar pages, or, you have to wait for IE to detect the script 10 times or so, then you have to go back in and manually choose to block it. 

Personalized Tracking List

Of course Google is going to be the number one offender here, since that's how they make money is by shoving ads in your face around every corner and making you want to buy stuff.  Honestly, I sympathize with online advertisers to a certain point, because I believe the internet would not have as much rich, free content as it does if internet advertisers were unable to make money by providing free services.  I mean, Google doesn't keep Youtube up just because they love paying those network bandwidth bills so much. But, the ads can quickly get simply too obnoxius, and we users need a way to filter all that junk that's flashed before our eyes.  Especially the Google ones that break Internet Explorer's back button.  It's Google's code that decides to open 4 instances of some doubleclick.net resource in a way that it causes you to have to hit the Back button in your browser 5 times to get back to where you were. From legalinsurrection.com

The flip-side of the coin is that if you block too much, certain websites will stop working properly. So you need to find a happy medium. Queue Tracking Lists.  Just like AdBlock, Tracking Lists are designed to block just the web content that has been decided is more harmful or annoying than good.  That way we can keep using our Gmail, Youtube, StackExchange, etc., without interruption, while still cutting out a good chunk of the ads.

You can download new Tracking Protection Lists online, right from within the tracking lists dialog box. Just click the "Get A Tracking Protection List Online..." link. It will take you to a website.  Notice in the screenshot above, that I have already added the "EasyList" TPL, from the same people that do AdBlock.  Also notice that the Tracking Protection List is simply an HTTP URI to a *.tpl text file.  And you know what that means... that means we can play with it from Powershell!

Say you wanted to examine a TPL and see if it contained a certain domain name. Well first, let's download the TPL and store it to a variable:

PS C:\> $list = Invoke-WebRequest http://easylist-msie.adblockplus.org/easylist.tpl

Now the content of the tracking list will be in $list.Content. These are the web resources that the list will block.  You can go here to see the syntax of TPLs. Warning: There will be distasteful words in this list... as the list is designed to block distasteful content.

Alright, so what if we want to know whether this TPL will block content from the domain streamcloud.eu. First, let's break $list.Content up into lines by splitting it on newlines:

PS C:\> $list.Content.Count
PS C:\> $Content = $list.Content.Split("`r`n")
PS C:\> $Content.Count

After splitting the content element of the web request on newlines, we can see that the TPL contains 10,203 lines. I first thought to split on [String]::NewLine, but that did not yield correct results. (Dat character encoding!) Now, keeping in mind that lines that start with a # are comments, let's see if we can find entries that contain streamcloud.eu:

PS C:\> foreach($_ in $Content) { If(!$_.StartsWith('#') -and $_.Contains("streamcloud.eu")) { $_ } }
-d streamcloud.eu /deliver.php
+d streamcloud.eu

So from this output, it appears that we are allowing streamcloud.eu, but we are specifically blocking any document named deliver.php coming from streamcloud.eu.  This could have also been written as:

PS C:\> foreach($_ in $Content) { If(!$_.StartsWith('#') -and $_ -match "streamcloud.eu") { $_ } }

But a lot of times I just naturally prefer the C# parlance. The good thing about Powershell is that you're free to mix and match.

You can certainly elaborate on the concept I've started on above, and I hope you will.  Until next time!

Signing Powershell Scripts

Hi guys,
Something you might know about me is that I think Powershell is just about the best thing to ever happen to Windows Server.  And even if you don't agree... well, you don't really have a choice because there are already tasks that must be done in Powershell and there is no GUI alternative, and that trend will only continue.
Powershell will become part of your life if you plan on continuing to work with Windows Server. PS is very powerful, and it makes many tasks much faster and more automatable.  But with that power, comes the side-effect that PS also makes many nefarious activities faster and easier as well.  An attacker has many more tools and methods (no pun intended) available to him or her if they have unrestricted access to Powershell on your server. You could restrict all Powershell usage on your servers, but that means losing an extremely valuable tool for administrators. There must be a compromise...

One effective way to mitigate this risk is to digitally sign your Powershell scripts with a certificate. By setting the execution policy of PS scripts on your servers to AllSigned, Powershell will not run scripts unless it can successfully validate the signature that is in the script.  That also means that the script cannot be modified after being signed, as the signature will no longer match the modified script.  This is much better than the RemoteSigned execution policy, which only mandates that scripts downloaded through an Attachment Execution Service-compliant application need to be signed, which is extremely easy to bypass. (e.g. just clear the alternate NTFS data stream.)
Good news is that code signing, especially in Powershell, is actually pretty easy to do.
First, as an administrator of an Active Directory domain with an Enterprise Certificate Authority, you need to make a code signing certificate for your users to use.  On your CA, open the Certificate Templates MMC snap-in.  You can also get there in the CA snap-in by right-clicking on Certificate Templates and choosing Manage.

Cert Templates

Duplicate the Code Signing template, so that you don't modify the original template.  Configure all the properties of this template as desired, including allowing Authenticated Users (or whichever users you desire) the ability to enroll in your new certificate template.

Cert Templates

I very creatively named my template "Code Signing Template v1."  Now go back to your Certificate Authority snap-in, and choose New -> Certificate Template to Issue.  Choose your new code signing cert.

Cert Templates

Keep in mind that this information is being uploaded to Active Directory, so make sure AD replication has taken effect before wondering why the certificate isn't already available at your location as soon as you issue it.

Now, on your workstation, where you are logged in as a regular user, you want to enroll for one of those new code signing certs.  You could do this in the Certificates MMC snap-in:

Cert Enrollment

But, since we like to save time, let's go ahead and instead submit the certificate request via Powershell:


You have to take the spaces out of the certificate template name.  But you'll know the certificate request was successful if the status is Issued.  You'll also notice that the public key of your new code signing cert is now published publicly in your Active Directory user account.  This is so everyone else in the domain can access your public key so that they can validate that you did, in fact, sign that exact Powershell script, so we can figure that it's safe to run.


Signing a Powershell script with your new code signing certificate is simple:

Powershell script sign

Just Set-AuthenticodeSignature $script $certificate, and it's signed.  The signature is actually a block of cipher-text that appears at the bottom of your newly signed script.


Script Signed

Your identity is also encoded in those comments, but is not encrypted.  So Powershell can tell who signed the script right off the bat.  Then, Powershell retrieves the public key of that identity (from AD for example.)  The script was signed using your private key, which you do not share, and can only be decrypted with your public key, which you do share.  So if Powersell is able to decode the signature with your public key, it can be reasonably assured that it was signed by you.  If the script changes by even a single character, then that hashed with your private key would result in an entirely different signature, therefore modification of the script means Powershell will not run it unless it is re-signed by another authorized user, and we would be able to tell who that was.
Alright, that's enough out of me.  Hopefully I've been able to at least pique your interest in the potential security benefits of code signing!

(And sorry for all the cheesy pixellation.)

Neat Windows Tricks (Or Back When I Was Young and Foolish Pt. III)

I work with Windows a lot. Almost every day of my life since Windows 3.1, I've been submersed in Windows for both work and play. Getting to know it inside and out. Learning new Windows applications. Being excited for new releases of Windows because I know it'll bring big changes to the operating system which will make me have to learn new things. Every now and then, I even start to think I'm pretty knowledgable about Windows...

Which is why I'm always flabbergasted when someone non-chalantly shows me a relatively mundane Windows trick I never knew about, yet it's been under my nose the whole time!  And so, I bring you two Windows tricks that I learned about today. If you already knew about them, you can just think of me as an amateur and move on.  But if you didn't already know about them, they might just change the way you do your daily work!

C:\> SomeCommand | clip

 I never knew about this! On the command line, you can pipe the output of any program or command to your Windows clipboard and Ctrl+V it anywhere!


You can also do something like

C:\> clip < textFile.txt to quickly copy the contents of the file to your clipboard.

Alright, trick #2:

Shift + Right-Click to Run as Different User

This one was down-right embarrassing for me to have not known. Maybe I did know it at one time, but then I used it so infrequently that I forgot about it... I don't know. Back in the XP/2003 days, you could right-click on an application and choose "Run as..." which would prompt you for the credentials of another user under which to to run that process. But then in Vista onwards it disappeared. Sure, there's still "Run as administrator," but sometimes you need to run a process as someone else besides Administrator. Well, I always just got around it by launching a command prompt and doing something like runas /user:BobMarley@domain.com notepad.exe.

But I completely forgot that it's still there in the GUI.  All you have to do is Shift+Right-click:


Now Powered By Windows Azure

I transferred this blog to Windows Azure today. Up until today, I've been hosting this blog from inside my home. While I can boast almost zero unplanned downtime even from my mostly consumer-grade hardware and residential internet connection, I felt it was time to hoist this blog up into a slightly more professional and resilient environment. That way I don't have to worry about backups and hardware failures on my own gear taking down this blog. And it gives me more flexibility in terms of being able to tear my home lab apart and rearrange it without having to affect this blog.

It was very easy to move the blog to the new VM on Azure, which is good, because I've been so busy at work lately that I've had time for little else... such as blogging. I had to sign up especially for the "preview" of VM hosting from Azure, as it is apparently still in the preview phase. You get about a 50% discount until it goes General Availability. Anyway, both the virtual machine and the portal have both worked perfectly so far and I would not be surprised if it was really close to GA. The portal looks nice, polished, and works well. Comes with a nice, basic resource monitor so you can see your VM's CPU, memory, network usage, etc. over time from the web portal. The price is pretty low. Definitely lower than some other providers. My external IP address won't change. Plus they can host Server 2012 VMs, which some other providers are still catching up to. I chose the absolute slowest, lowest-spec VM that they would give me, because of the price. So the machine is a little slower than it was running on my own gear, but it's still enough for this measly blog. After the VM was done being imaged, I loaded IIS and SMTP on it, simply dumped the whole inetpub directory straight from my home machine into the VM, configured SMTP (so comment emails can be sent from this blog to my Gmail account, etc.,) and then turned the GUI off on the server with Powershell and logged out. Piece of cake.

Azure actually offers a lot of different hosting capabilities - not just virtual machines. In fact I don't think Azure even realized that they would offer IaaS when they first set out. But I chose the VM option because I'm most comfortable managing the OS myself... learning how to set up Visual Studio to publish websites from my desktop straight into an Azure service is totally new to me and I haven't even begun learning how to do that yet.