• Troubleshooting Microsoft Group Policy Site to Zone Mapping Using Microsoft PowerShell

    March 4, 2016

    Active Directory, Blog

    One of the nice things about being an independent consultant is the new stuff learned while on projects. I learned some new information about Site to Zone Mapping I wanted to share with you.

    [Testing updates are at the bottom of the article. Article last updated 5-Oct-2016.]

    A project I worked on recently had users complaining about how long it took to logon and launch their published applications. As is my practice, the first thing I start doing is looking in the event logs. One of this issues I found was this mysterious message in the System event log:

    Windows failed to apply the Internet Explorer Zonemapping settings

    OK, what group policy did this come from? Is this really a problem? Was this slowing down the logon or application launch?

    I did a quick PowerShell script to gather all the 1085 EventIDs from the System event log from their hundreds of XenApp 6.5 servers. What I found was there were many hundreds of these events every day on every XenApp server. Looking in the details, I saw this was causing an issue with logons and application launches.

    The shortest delay I found was:

    Figure 1
    Figure 1

    The longest delay I found was:

    Figure 2
    Figure 2

    Most of the delays were in the 5 to 6 second range.

    Now to find out what group policy was causing the issue.

    The cached copies of profiles are deleted so I couldn’t run a Resultant Set of Policy on a user’s name or the server. Since I am an outsider with limited account access and limited visibility into Active Directory, I turned to the lab on my laptop. I built a test group policy with a few Site to Zone Mapping entries and saw that the settings were saved in a file called seczones.inf. Next step was to borrow some code that Michael B. Smith wrote for the XenApp 6.5 documentation script that traverses SYSVOL looking for the Citrix group policy file. I slightly modified Michael’s code to look for the seczone.inf file instead of the policies.gpf file.

    Here is the code I used to scan SYSVOL looking for all policies that contain a seczone.inf file.

    $pwdpath = $pwd.Path
    
    If($pwdpath.EndsWith("\"))
    {
    	#remove the trailing \
    	$pwdpath = $pwdpath.SubString(0, ($pwdpath.Length - 1))
    }
    [string]$FileName1 = "$($pwdpath)\SecZonePolicies.txt"
    $root = [ADSI]"LDAP://RootDSE"
    $domainNC = $root.defaultNamingContext.ToString()
    $root = $Null
    $xArray = @()
    
    $domain = $domainNC.Replace( 'DC=', '' ).Replace( ',', '.' )
    Write-Host "$(Get-Date): Searching \\$($domain)\sysvol\$($domain)\Policies"
    $sysvolFiles = @()
    $sysvolFiles = dir -Recurse ( '\\' + $domain  + '\sysvol\' + $domain + '\Policies' ) -EA 0
    If($sysvolFiles.Count -eq 0)
    {
    	Write-Host "$(Get-Date): Search timed out.  Retrying.  Searching \\ + $($domain)\sysvol\$($domain)\Policies a second time."
    	$sysvolFiles = dir -Recurse ( '\\' + $domain  + '\sysvol\' + $domain + '\Policies' ) -EA 0
    }
    
    ForEach( $file in $sysvolFiles )
    {
    	If( -not $file.PSIsContainer )
    	{
    		#$file.FullName  ### name of the policy file
    		If( $file.FullName -like "*\User\microsoft\IEAK\BRANDING\ZONES\seczones.inf" )
    		{
    			#"have match " + $file.FullName ### name of the Citrix policies file
    			$array = $file.FullName.Split( '\' )
    			If( $array.Length -gt 7 )
    			{
    				$gp = $array[ 6 ].ToString()
    				$gpObject = [ADSI]( "LDAP://" + "CN=" + $gp + ",CN=Policies,CN=System," + $domainNC )
    				$xArray += $gpObject.DisplayName	### name of the group policy object
    			}
    		}
    	}
    }
    
    $cnt = 0
    If($xArray -is [array])
    {
    	$cnt = $xArray.Count
    	$xArray = $xArray | Sort
    }
    Else
    {
    	$cnt = 1
    }
    
    Write-Host "$(Get-Date): Output list of $($cnt) policies"
    Out-File -FilePath $Filename1 -InputObject $xArray
    
    If(Test-Path "$($FileName1)")
    {
    	Write-Host "$(Get-Date): $($FileName1) is ready for use"
    }
    

    Running this script produces a sorted list of policies that need further research. Just because a policy folder contains a seczones.inf file does not mean that policy contains Site to Zone Mapping. Now I needed to review every policy to see which ones actually use Site to Zone Mappings. As I reviewed each policy (by looking at the Settings tab for the GPO), I copied the Site to Zone Mappings to Excel. Once all policies had been reviewed, I used Excel to remove all the duplicate entries and sorted the remaining entries.

    So what entries were causing the problem? What exactly are valid entries?

    I reached out to Group Policy MVP Jeremy Moskovitz (owner of PolicyPak and GPAnswers) for help. He then reached out to a friend of his, Martin Binder, who sent back some useful information. The reply from Martin about what is valid and invalid:

    This is a bug in how Windows processes the lists in that policy setting.
    
    The only valid items are:
    
    Valid: [(http|ftp|someotherprotocol|*)://](Host|*).dom.tld
    (The protocol spec is optional...)
    
    Everything else is invalid.
    
    *.tld - invalid
    www.google.com/maps - invalid
    www.bing.*- invalid
    *cdn.amazon.com - invalid
    *tp://www.policypak.com - invalid
    *.*.microsoft.com - invalid
    
    Tip:
    
    In Win10, 2 letter domains like *.co.au or *.co.nz are now allowed. 
    These were forbidden in earlier windows versions and threw errors and possibly caused slowdowns.
    

    Being the Sm@rt@$$ that I am, I now had to prove his list and test what now looked like the invalid entries in the customers Site to Zone Mappings.

    My laptop lab’s domain controller is Server 2012 R2 and the Forest Functional Level is 2012 R2. By this time, the customer had granted me much higher level of access so I was able to do a small test in their 2003 Forest and their 2008 R2 Forest. Results were the same in all three Forests.

    I created a test VM, joined to the domain and logged in with local administrator credentials for the tests.

    The first thing I did was create a Site to Zone mapping with a known valid entry of https://Receiver.Citrix.com in zone 2.

    Figure 3
    Figure 3

    On my test VM I then ran GPUpdate /force, open Internet Explorer (IE), looked at my Trusted Sites and my entry was there.

    Figure 4
    Figure 4

    Next I wanted to try what looked like an invalid entry from the customer, a URL with no Zone number.

    Figure 5
    Figure 5

    Running GPUpdate /force, gives me:

    Figure 6
    Figure 6

    So a URL with no Zone number is an invalid entry. Looking at my Trusted Sites shows just the original entry is there.

    Figure 7
    Figure 7

    Another possible invalid entry from the customer. Notice the * after the .com.

    Figure 8
    Figure 8

    Running GPUpdate /force shows that putting an * after the TLD is an invalid entry.

    Figure 9
    Figure 9

    What about a popular entry of putting a port number in the URL?

    Figure 10
    Figure 10

    Running GPUpdate /force shows success.

    Figure 11
    Figure 11

    Or is it?

    Figure 12
    Figure 12

    What happened to the port number? It is not even saved in the registry. So adding a port number is invalid but the valid data before the port number is saved.

    Figure 13
    Figure 13

    Now let’s go through the list of invalid entries from Martin.

    *.tld

    Figure 14
    Figure 14

    GPUpdate /force shows it is an invalid entry.

    Figure 15
    Figure 15

    Next on the list is www.google.com/maps.

    Figure 16
    Figure 16

    GPUpdate /force appears to like what he said was an invalid entry.

    Figure 17
    Figure 17

    But Trusted Sites shows anything after the TLD is removed. Just like with adding a port number, anything after the TLD is just removed.

    Figure 18
    Figure 18

    Next up on the list is www.bing.*.

    Figure 19
    Figure 19

    I can tell you that GPUpdate /force didn’t like that entry so I will not bother you with another image of that.

    Next up is *cdn.amazon.com.

    Figure 20
    Figure 20

    Trust me, that is not valid and neither is *tp://www.policypak.com or *.*.Microsoft.com.

    My next question is what happens if you have a mix of valid and invalid entries.

    Figure 21
    Figure 21

    Obviously GPUpdate /force is not going to like this.

    Figure 22
    Figure 22

    But what does my Trusted Sites show.

    Figure 23
    Figure 23

    Did you notice that the entries in my Trusted Sites does not match the order they were entered in the policy?  It appears Trusted Sites is a sorted list and all capitalization is removed.

    What I would like to see is the Warning in the System event log would give more information. For example, what group policy caused the warning and what mappings are invalid. There is just not enough information in the recorded event.

    Figure 24
    Figure 24
    Figure 25
    Figure 25

    What I learned:

    • Using Site to Zone Mappings is expensive
    • The more Mappings you use, the more time it takes
    • If there are any invalid Mapping entries, the time increases even more
    • All capitalization is removed
    • The URLs placed into the various Zones are sorted

    As I was wrapping this up, I was asked about *://domain.tld. So of course I had to test it.

    Figure 26
    Figure 26

    Running GPUpdate /force and it is valid. What shows in Trusted Sites is:

    Figure 27
    Figure 27

    *://CarlWebster.com becomes just *.carlwebster.com.

    If you have any other URLs you would like me to test, just email me. Webster@carlwebster.com

    Thanks for your help Jeremy and Martin.

    Update 5-Mar-2016: Someone asked about the time savings. If we use an average delay of six seconds and add a delay for one logon and one application launch that is a total delay of 12 seconds per day per user. If we low ball the number of users to 2000 then that is 24000 seconds lost. 24000 seconds divided by 3600 (the number of seconds in an hour) we get 6.67 hours lost per day. Multiply that by more users and more application launches and we start getting into real time lost which costs real money and cost real productivity.

    Update 7-Mar-2016: Someone asked me to test http://10.218.* and it is invalid but http://10.218.*.* is valid.

    Figure 28
    Figure 28

    My tests were done on the User Configuration but you should see the same on the Computer Configuration.

    Does this Event ID only get recorded for this warning? To test, I cleared my Application Event Log and ran GPUpdate /force. The only entry now is “Security policy in the Group policy objects has been applied successfully.” In the Group Policy event log, I get the following three events recorded:

    Completed Security Extension Processing in 297 milliseconds.
    Completed manual processing of policy for computer WEBSTERSLAB\XA652$ in 1 seconds.
    Next policy processing for WEBSTERSLAB\XA652$ will be attempted in 99 minutes.

    Next question is does the time it take for processing Site to Zone Mappings still the same when all entries are valid as when there are invalid entries? I don’t have enough entries in my lab to know. When I do Change Control for the customer and fix all their Site to Zone mapping policies, I will let you know what I find out.

    Update #2 7-Mar-2016:

    I found the following three articles from Microsoft and will test more patterns.

    IInternetSecurityManager::SetZoneMapping method
    Problems Adding Top-Level Domains to Zone Sites List
    Internet Explorer’s Explicit Security Zone Mappings

    Tested the following patterns from the articles:

    *://*.example.com – Valid, becomes *.example.com
    http://*.contoso.co.uk  – Valid
    *://server.contoso.com – Valid, becomes server.contoso.com
    ftp://192.168.0.0/ – Valid
    https://example/ – Valid
    file:\example\share – Invalid even though the first article says it is valid
    *://172.16-31.0.0.* – Valid, becomes 172.16-31.0.0

    http://*.server.example.com – Valid even though the first article says it is invalid
    ftp://* – Invalid

    I then tested file:\\example\share and that shows as Valid but becomes file://example (the \share is dropped).

    Patterns from the second article that are not in the first article.

    ftp://157.54.23.41/ – Valid
    file:\\localsrv\share – Valid but becomes file://localsrv (the \share is dropped)
    *://157.54.100-200.* – Valid but becomes 157.54.100-200.*

    After seeing the *://172.16-31.0.0.*  and *://157.54.100-200.* examples, I wondered how far that could be taken.

    192-193.0.0.0 is Valid.
    192-193.1-10.0.0 is Valid
    192-193.1-10.20-30.0 is Valid
    192-193.1-10.20-30.40-50 is Valid

    Update 10-Mar-2016: Martin wrote an article on Internet Explorer site to zone assignments – is it valid and why not? Check it out.

    Update 5-Oct-2016: Reader left a comment wanting two tests run. file:\\1.2.3.4 [with a valid IP address] and file:\\ComputerName [valid computer name with no domain added].

    Here are the GPO settings.

    Figure 29
    Figure 29

    I forced replication between my two domain controllers, did a gpupdate /force and even restarted the servers just to make sure. Running gpupdate /force reported no errors but neither entry appears in the Trusted Sites zone.

    Figure 30
    Figure 30

    Thanks

    Webster

    About Carl Webster

    Webster is a Sr. Solutions Architect for Choice Solutions, LLC and specializes in Citrix, Active Directory and Technical Documentation. Webster has been working with Citrix products for many years starting with Multi-User OS/2 in 1990.

    View all posts by Carl Webster

    11 Responses to “Troubleshooting Microsoft Group Policy Site to Zone Mapping Using Microsoft PowerShell”

    1. Stephan Says:

      Hi Carl,

      we’re struggling with adding mapped network drives like X:\
      Already tried many constellations like
      file://X:\
      file:\\X:\
      file:\X:\
      file://\\X:\

      Adding the computer wich contains the mapped drive by name or ip-address doesn’t help either.

      Any ideas?

      Thank You and cheers,
      Stephan

      Reply

    2. Sami Närhi Says:

      Excellent article – Thanks
      I have found out that *.gov.uk and similar ‘two top level’ domains with asterisk give error message as well. (they are listed in registry zonemapkey but not in domains).
      Do you know is there maximun number of sites/lines that can be added to zone aligment list?

      Reply

      • Carl Webster Says:

        In the article by Martin referenced in my article, he states:

        “Remark: In earlier versions of windows, if you provided a wildcard with a second level domain with only two letters (*.co.uk e.g.), this was an invalid entry. This was to prevent the whole SLD of some countrys to be added. At the time of this writing, this type of entry has become valid in Windows 10.”

        http://evilgpo.blogspot.de/2016/03/internet-explorer-site-to-zone.html

        Thanks

        Webster

        Reply

    3. Mike Says:

      Great article !
      I’m looking to optimize the logon speed as much as possible, so this was an interesting topic.
      In my secure environment, not connected to the internet, our Site to Zone assignment list contains many IP addresses of individual hosts.
      Do you think logon processing would be quicker replacing with one or two wildcard entries ?

      eg.
      10.100.1.1
      10.100.1.3
      10.100.1.6
      10.100.1.9
      10.100.3.7
      10.100.3.8
      10.100.3.9
      10.100.4.3
      10.100.5.3

      ..

      replacing with
      10.100.1-5.*

      Reply

      • Carl Webster Says:

        You may gain a thousandth of a second or so but I believe you will gain more in management. I would rather see a short list than a long list. You would then, also, be able to see the list in the grey out zone mappings box in IE.

        Webster

        Reply

        • Mike Says:

          That was my other concern, the administrative burden of adding entries and potential for a typo. Thanks, think I’ll wildcard them. (the joys of inheriting a setup from a departed sys admin)

          Reply

    4. Joachim Says:

      Thanks for this great post!

      Would you mind testing the following:

      file:\\192.168.0.1
      or another working IP address

      and also

      file:\\servername
      without the domain

      Reply

    5. Erik Ardengård Says:

      Great one! Thanks.

      Reply

    6. Alain Assaf Says:

      Great article Carl. You really pulled back the veil on these site to zone error messages which I’ve encountered for years.

      Reply

    Leave a Reply