Contact

Subscribe via Email

Subscribe via RSS/JSON

Categories

Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan

Elsewhere

ADFS WIA Support UserAgent strings for Chrome etc.

This is more as a note to myself. Out of the box ADFS does not have WIA enabled for most browsers. You need to add the UserAgent strings of browsers you wish to enable WIA for. Here is the cmdlet with the list of agents I currently use:

This is based on this & this Microsoft Docs plus some other blog posts I read over the years. I will keep updating this blog post with any updates. 

It might be better to replace “Chrome” above with “Windows\s*NT.*Chrome”. I found this in the comments of this article. Useful so it only targets Chrome on Windows and not iOS/ Android. 

Here’s the User Agent Strings from Safari on my iPhone, Mac Book, and Vivaldi on Windows. 

  • Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1
  • Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.2 Safari/605.1.15
  • Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36 Vivaldi/2.1.1337.36

Matching on “Windows\s*NT.*Chrome” (which I think is regex and so should translate to the string Windows followed by zero or more spaces, followed by NT, followed by zero or more characters, followed by Chrome) will thus only pick the last User Agent String. 

Some more things to be done for WIA to work. You must add your ADFS site to the Local Intranet zone of IE. Best to use Group Policy Preferences for this, pushing out a registry key. Under the HKCU hive you can push out a key “Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\adfs.fqdn\” (or replace adfs with a * if you want *.fqdn to be matched), with a value of https and data of DWORD 00000001 in hex. Chrome, and Chromium based browsers (such as Vivaldi, Edge, etc.) will use this list so WIA will work for them automatically. 

This link from the Chromium page also mentions the SPN issue I encountered previously. The SPN generated will use the CNAME name if that exists, so better to use an A record with an IP address. 

When a server or proxy presents Chrome with a Negotiate  challenge, Chrome tries to generate a Kerberos SPN (Service Principal Name) based on the host and port of the original URI. Unfortunately, the server does not indicate what the SPN should be as part of the authentication challenge, so Chrome (and other browsers) have to guess what it should be based on standard conventions. 

The default SPN is: HTTP/<host name>, where <host name> is the canonical DNS name of the server. This mirrors the SPN generation logic of IE and Firefox.

ADFS and CNAME records – HTTP/400 error with WIA

I had heard that it is better to create an A record for ADFS (i.e. you get an IP address as the reply when querying the record) rather than a CNAME record (i.e. you get a name and the IP address of that alternate name) but didn’t know why until today. Now I know at least one reason why it is better to have an IP address. 

To begin with I must point to this blog post. The author had the same error as me, but of course he wasn’t using a CNAME, so his actual problem and fix was different. But the blog post is worth a read to know the situation. I had two domains – Domain A and Domain B – each with ADFS servers. I was trying to access the ADFS server in Domain B from a machine in Domain A, and getting prompted for credentials (expected) but once I enter the correct details it would give me an HTTP/400 error. Disabling WIA and enabling Forms Based Authentication worked, so the problem was to do with WIA. These are different domains, with trusts in place, and I was entering the correct details … so what gives? 

Looking at the System logs on my machine in Domain A (not where the ADFS server is in) I had entries like this:

The Kerberos client received a KRB_AP_ERR_MODIFIED error from the server msvc_adfs2$. The target name used was HTTP/rak2addc01.two.raxnet.global. This indicates that the target server failed to decrypt the ticket provided by the client. This can occur when the target server principal name (SPN) is registered on an account other than the account the target service is using. Ensure that the target SPN is only registered on the account used by the server. This error can also happen if the target service account password is different than what is configured on the Kerberos Key Distribution Center for that target service. Ensure that the service on the server and the KDC are both configured to use the same password. If the server name is not fully qualified, and the target domain (TWO.RAXNET.GLOBAL) is different from the client domain (TWO.RAXNET.GLOBAL), check if there are identically named server accounts in these two domains, or use the fully-qualified name to identify the server.

The highlighted entry is the clue. I was accessing the ADFS server as adfs.two.raxnet.global, and it was a CNAME to rak2addc01.two.raxnet.global, so looks like during WIA it was using the CNAME instead of the actual name and hence using the SPN HTTP/rak2addc01.two.raxnet.global rather than HTTP/adfs.two.raxnet.global. It also seemed to be using the (correct) HTTP/adfs.two.raxnet.global SPN and identifying the associated service account msvc_adfs2 but since that service account couldn’t decrypt the Kerberos tickets, I was getting an error.

Restore-GPO : Value does not fall within the expected range

Once in a while you Google on some error and come across an old blog post of yours … and you smile. :) That’s what happened today. I was trying to Backup-GPO and Restore-GPO between two (trusted) domains and got the above error. Turns out this is expected when restoring GPOs between domains and I had encountered it previously. The workaround is to make a new GPO in the target domain and import the settings from the backed up GPO. 

You can either do this via PowerShell – use the Import-GPO cmdlet, or via GPO – right click the GPO and select “Import Settings”. 

Funny, the post I found was from 6 years ago … had forgotten I used to play with this stuff back then too. 

ADFS 2016 prompts for credentials via a popup (and doesn’t work)

Setup ADFS in my home lab. There’s a single server called rak1adfs01.raxnet.global. The ADFS service is called adfs.raxnet.global and in DNS this is a CNAME to the server. 

When I go to https://adfs.raxnet.global/adfs/ls/IdpInitiatedSignon.htm I get a login prompt and even though I enter the correct credentials it doesn’t let me in. This is unlike what I am used to at work where we get a forms based screen and that works. 

To troubleshoot this I went to the authentication options on ADFS and under the Intranet section I unticked Windows Authentication and Microsoft Passport Authentication, leaving only Forms Authentication ticked. 

Screen Shot 2018 12 14 at 5 59 50 PM

Restarted the ADFS service and went back to ADFS page again – voila! it signs in. So the issue is definitely the WIA authentication. 

I noticed that when the prompt comes up it has my server name in it (rak1adfs.raxnet.global) rather than the ADFS service name (adfs.raxnet.global). That didn’t make sense – sounded like my browser was trying to authenticate against the server directly. 

Screen Shot 2018 12 14 at 6 03 18 PM

Could be an SPN issue? According to this article I am supposed to have an SPN of the form host/adfs.raxnet.gloabal and that does exist. 

Looking at the SPNs of rak1adfs01.raxnet.global (my ADFS server) I don’t see anything tying it to my service account. I came across another article, for a single ADFS server, which suggests setting up an SPN for http/<servername>. 

Once I did that WIA started working. (If I delete this SPN and create one for http/adfs.raxnet.global WIA fails again. I guess my issue is that since it’s a single server currently it is being treated as a single server case rather than an ADFS farm). 

I went back and enabled the Forms Authentication and everything works as usual. 

Lessons learnt: 1) WIA takes precedence over Forms Based Authentication; and 2) SPNs must be created against the single server if you have a single server install (even though you might be thinking of it as a farm install because you plan on installing more servers later). 

As an aside, some useful links: 

  • Here’s an example of a simple authentication app you can setup that uses ADFS
  • If you don’t want to install an app but just want to test ADFS authentication you can always go to https://fqdn.domain.com/adfs/ls/IdpInitiatedSignon.aspx. This will only work on ADFS 2016 if you enable it
  • Lastly, one more SAML test app that you can install. 
  • The two SPNs that are required for ADFS.

New ADFS configuration wizard does not pick up SSL certificate

Was setting up ADFS in my  home lab and I encountered the following issue. Even though I had a certificate generated and imported to the personal certificate store of the ADFS server, it was not being picked up by the configuration wizard. 

EmptyCert

I tried exporting the certificate with its private key as a PFX file and clicking the Import button above. Didn’t help either.

I also tried the following which didn’t help (but since I took some screenshots and I wasn’t aware of this way of tying certificates to a service account, I thought I’d include it here anyways). 

Launch mmc and add the Certificates snap-in. Choose Service account

Certificates

Then Local Computer. And Active Directory Federation Services

ADFS-Cert

Import the PFX certificate to its personal store. 

This too didn’t help! 

Finally, what did help was create a new certificate but use the CN and SAN name different to the server name. As in, my original certificate had a CN of “myservername.fqdn” along with some SANs of “myservername.fqdn” and “adfs.fqdfn” (the latter being what my ADFS federation service name would have been) but for the new cert I generated I went with a CN of “adfs.fqdn” and SANs of “adfs.fqdn” and “myservername.fqdn”. That worked!

[Aside] Offline CRL errors when requesting a certificate

This blog post saved my bacon many times in my home lab. 

Remember this command: 

Having both DHCP server and PXE server as IP Helpers

I always thought you don’t specify a PXE server in the list of IP Helpers. Rather, you specify DHCP servers, and the DHCP servers have options 66 (boot server) and 67 (boot file name) which specify the PXE server name. Turns out I was wrong. I recently saw that at work we have both a DHCP and PXE server defined as IP helpers, and the DHCP server didn’t have any options 66 & 67 specified, yet things worked fine. How was that possible?

Turns out that is because you can specify both DHCP servers and PXE servers as IP helpers (and if you don’t have IP helpers, you can have both DHCP servers and PXE servers on the same LAN as clients … listening to requests and replying). There won’t be a clash. This is because the PXE client (which is the component on the client machine that does PXE booting) will take the IP address from the DHCP server and the PXE details from the PXE server. This article cleared things for me, here’s some excerpts:

PXE does not come with a dedicated boot protocol. It is simply DHCP packets extended with additional DHCP options. It’s formerly known as the bootstrap protocol. If a PXE-enabled network card sends out an DHCP discover package, it will add DHCP option 60, which includes the string “PXEClient:Arch:xxxxx:UNDI:yyyzzz”. Then it waits for DHCP offers.

It will only respond if it gets a DHCP offer including option 60 which means: I am PXE capable and able to send out boot server and boot file information.

The DHCP offer can be splitted into two independent packages, coming from different servers. The DHCP server can send out the DHCP offer containing the clients IP address and the PXE server can send out the DHCP offer containing the option 60.

Check out that article for some WireShark captures and traffic flows.

The PXEClient option is useful when you want to specify separate policies for BIOS and UEFI clients. Check out this article for more info on that.

DNS SRV records used by AD

Just thought I’d put these here for my own easy reference. I keep forgetting these records and when there’s an issue I end up Googling and trying to find them! These are DNS records you can query to see if clients are able to lookup the PDC, GC, KDC, and DC of the domain you specify via DNS. If this is broken nothing else will work. :)

PDC _ldap._tcp.pdc._msdcs.<DnsDomainName>
GC _ldap._tcp.gc._msdcs.<DnsDomainName>
KDC _kerberos._tcp.dc._msdcs.<DnsDomainName>
DC _ldap._tcp.dc._msdcs.<DnsDomainName>

You would look this up using nslookup -type=SRV <Record>.

As a refresher, SRV records are of the form _Service._Proto.Name TTL Class SRV Priority Weight Port Target. The _Service._Proto.Name is what we are looking up above, just that our name space is _msdcs.<DnsDomainName>.

[Aside] Printer Objects in AD

I knew printer objects were present in AD but had no idea where to go look for them. Today I had a need to, and this post helped.

[Aside] Various DPM 2016 links

Reading up on (and trying to work with) DPM 2016 nowdays so here’s some links to myself before I close them from the browser:

Copy the path and save it in a notepad. It’ll look like the following. E:\ on DPM2016TP5-01.contoso.local C:\Program Files\Microsoft System Center 2016\DPM\DPM\Volumes\Replica\31d8e7d7-8aff-4d54-9a45-a2425986e24c\d6b82768-738a-4f4e-b878-bc34afe189ea\Full\E-Vol\

The first part of the copied string is the source. The second part, separated by a whitespace, is the destination. The destination contains the following information:

DPM Install Folder          C:\Program Files\[..]\DPM\Volumes\Replica\

Physical ReplicaID          31d8e7d7-8aff-4d54-9a45-a2425986e24c\

Datasource ID                   d6b82768-738a-4f4e-b878-bc34afe189ea\

Path                                        Full\E-Vol\

 

TIL: Network access: Restrict clients allowed to make remote calls to SAM

Today I learnt of this setting. I was seeing messages like the following on a couple of my servers and read the link:

1 remote calls to the SAM database have been denied in the past 900 seconds throttling window.
For more information please see http://go.microsoft.com/fwlink/?LinkId=787651.

This part gives you a gist of the matter:

The SAMRPC protocol makes it possible for a low privileged user to query a machine on a network for data. For example, a user can use SAMRPC to enumerate users, including privileged accounts such as local or domain administrators, or to enumerate groups and group memberships from the local SAM and Active Directory. This information can provide important context and serve as a starting point for an attacker to compromise a domain or networking environment.

To mitigate this risk, you can configure the Network access: Restrict clients allowed to make remote calls to SAM security policy setting to force the security accounts manager (SAM) to do an access check against remote calls. The access check allows or denies remote RPC connections to SAM and Active Directory for users and groups that you define.

By default, the Network access: Restrict clients allowed to make remote calls to SAM security policy setting is not defined. If you define it, you can edit the default Security Descriptor Definition Language (SDDL) string to explicitly allow or deny users and groups to make remote calls to the SAM. If the policy setting is left blank after the policy is defined, the policy is not enforced.

The default security descriptor on computers beginning with Windows 10 version 1607 and Windows Server 2016 allows only the local (built-in) Administrators group remote access to SAM on non-domain controllers, and allows Everyone access on domain controllers. You can edit the default security descriptor to allow or deny other users and groups, including the built-in Administrators.

So it looks like in my case some remote computer was trying to access this server’s SAM database (this is a server 2016 BTW) and it wasn’t in the local admin group of this server.

[Aside] Query remote RDP sessions and kill them

If you want to query the remote RDP sessions on a machine:

And to disconnect:

[Aside] Easily switch between multiple audio outputs using SoundSwitch

Via the always helpful How-To Geek – if you have multiple audio output devices on Windows 10 (e.g. HDMI, regular headphones via the headphone jack, a couple of Bluetooth headphones) like I do, and always right click the volume icon and change default devices and wished there was an easier & faster way to do this, look no far! Check out SoundSwitch. :) Open Source and actively developed too.

Ops Manager – PowerShell script failed

I was getting PowerShell script failed errors for one of our servers being monitored via SCOM. The error was along these lines:

Not having much of an idea as to what the matter is (but having a hunch that it must be to do with performance monitors) I took a look at the events logs on the server and found entries like these:

There were many more like this (I found them all in the Administrative Events). To fix this I rebuilt the performance counters.

One caveat: the instruction in the link above ask us to go to “c:\windows\system32” and run a command “lodctr /R“. This gave me an error: “Error: Unable to rebuild performance counter setting from system backup store, error code is 2”.

From a forum post I learnt that going to “c:\windows\syswow64” instead does the trick. So keep that in mind. :)

Service SIDs etc.

Just so I don’t forget. 

The SCOM Agent on a server is called “Microsoft Monitoring Agent”. The short service name is “HealthService” and is set to run as Local System (NT Authority\System). Although not used by default, this service also has a virtual account created automatically by Windows called “NT SERVICE\HealthService” (this was a change introduced in Server 2008). 

As a refresher to myself and any others – this is a virtual account. – i.e. a local account managed by Windows and one which we don’t have much control over (like change the password etc). All services, even though they may be set to run under Local System can also run in a restricted mode under an automatically created virtual account “NT Service\<ServiceName>”. As with Local System, when a service running under such an account accesses a remote system it does so using the credentials of the machine it is running on – i.e. “<DomainName>\<ComputerName>$“.

Since these virtual accounts correspond to a service, and each virtual account has a unique SID, such virtual accounts are also called service SIDs. 

Although all services have a virtual account, it is not used by default. To see whether a virtual account is used or not one can use the sc qsidtype command. This queries the type of the SID of the virtual account. 

A type of NONE as in the above case means this virtual account is not used by the service. If we want a service to use its virtual account we must change this type to “Unrestricted” (or one could set it to “Restricted” too which creates a “write restricted” token – see this and this post to understand what that means). 

The sc sidtype command can be used to change this. 

A service SID is of the form S-1-5-80-{SHA1 hash of short service name}. You can find this via the sc showsid command too:

Note the status “Active”? That’s because I ran the above command after changing the SID type to “Unrestricted”. Before that, when the service SID wasn’t being used, the status was “Inactive”. 

So why am I reading about service SIDs now? :) It’s because I am playing with SCOM and as part of adding one of our SQL servers to it for monitoring I started getting alerts like these:

I figured this would be because the account under which the Monitoring Agent runs has no permissions to the SQL databases, so I looked at RunAs accounts for SQL and came across this blog post. Apparently the in thing nowadays is to change the Monitoring Agent to use a service SID and give that service SID access to the databases. Neat, eh! :)

I did the first step above – changing the SID type to “Unrestricted” so the Monitoring Agent uses that service SID. So next step is to give it access to the databases. This can be done by executing the following in SQL Management Studio after connecting to the SQL server in question:

The comments explain what it does. And yes, it gives the “NT Service\HealthService” service SID admin rights to the server. I got this code snippet from this KB article but the original blog post I was reading has a version which gives minimal rights (it has some other cool goodies too, like a task to create this automatically). I was ok giving this service SID admin rights.