In today’s blog entry I’ll be doing a deep dive into how the Microsoft Web Application Proxy (WAP) established a trust with the Active Directory Federation Service (AD FS) (I’ll be referring to this as registration) in order to act as a reverse proxy for AD FS. In my first entry into this series I covered the business use cases that would call for such an integration as well as providing an overview of the lab environment I’ll be using for the series. So what does registration mean? Well, the best way to describe it is to see it in action.
Figuring out how to capture the conversation took some trial and error. This is where Sysinternals Process Explorer comes into play. I went through the process of registering the WAP with AD FS using the Remote Access Management Console configuration utility and monitored the running processes with Process Explorer. Upon reviewing the TCP/IP activity of the Remote Access Management Console process (RAMgmtUI.exe) I observed TCP connectivity to the AD FS farm.
The process is running as the logged in user, in my case the administrator account I’ve configured. This meant I would need to run Fiddler using the logged in user context rather than having to do some funky with running it as SYSTEM or another security principal using PSEXEC.
I started up Fiddler and configured it to intercept HTTPS traffic as per the configuration below. Ensure that you’ve trusted the Fiddler root certificate so Fiddler can establish a man-in-the-middle (MITM) scenario.
I next ran the Remote Access Management Console and initiated the Web Application Proxy Configuration wizard. Here I ran the wizard a few different times specifying invalid credentials on the AD FS server to generate some web requests. The web conversation below popped up Fiddler.
Digging into the third session shows an HTTP POST to sts.journeyofthegeek.com/adfs/Proxy/EstablishTrust with a return code of 401 Unauthorized which we would expect given our application doesn’t know if authentication is required yet and didn’t specify an Authorization header.
Session four shows another HTTP POST to the same URL this time with an Authorization header specifying Basic authentication with our credentials Base64 encoded. We receive another 401 because we have invalid credentials which again is expected.
What’s interesting is the JSON object being posted to the URL. The JWT includes a key named SerializedTrustCertificate with a value of a Base64 encoded public-key certificate as the value.
Copy and pasting the encoded value to notepad and saving the file with a CER extension yields the certificate below of which the WAP has both the public and private key pairs. The certificate is a 2048-bit key length self-signed certificate.
At this point the WAP will attempt numerous connections to the /adfs/Proxy/GetConfiguration URL with a query string of api-version=2 as seen in the screenshot below. It will receive a 401 back because Fiddler needs a copy of the client certificate to provide to the AD FS server. At this point I let it time out and eventually the setup finished.
So what does the configuration information look like from AD FS when it’s successfully retrieved? So to see that we have to now pay attention to the Microsoft.IdentityServer.ProxyService.exe process which runs as the Active Directory Federation Services service (adfssrv).
Since the process runs as Network Service I needed to get a bit creative in how I captured the conversation with Fiddler. The first step is to export the public-key certificate for the self-signed certificate generated by the WAP, name it ClientCertificate.cer, and to store it in the Network Service profile folder in C:\Windows\ServiceProfiles\NetworkService\Documents\Fiddler2. By doing this Fiddler will use that certificate for any website requiring client certificate authentication.
The next step was to start Fiddler as the Network Service security principal. To do this I used PSEXEC with the following options:
Psexec -i -u “NT AUTHORITY\Network Service” “C:\Program Files (x86)\Fiddler2\Fiddler.exe.
I then restarted the Active Directory Federation Service on the WAP and boom there are our successful GET from the AD FS server at the /adfs/Proxy/GetConfiguration URL.
The WAP receives back a JSON object with all the configuration information for the AD FS server as seen below. Much of this is information about endpoints the AD FS server is supporting. Beyond that we get information the AD FS service configuration. The WAP uses this configuration to setup its bindings with the HTTP.SYS kernel mode driver. Yes the WAP uses HTTP.SYS in the same way AD FS uses it.
So what did we learn? When establishing the trust with the AD FS server (I’m branding this registration 🙂 ) the WAP does the following:
- Generates a 2048-bit self-signed certificate
- Opens an HTTPS connection with an AD FS server
- Performs a POST on /adfs/Proxy/EstablishTrust providing a JSON object containing the public key certificate and authenticating to the AD FS server with the credentials provided with the wizard using Basic authentication.If the authentication is successful the AD FS server establishes the trust. (I’ll dig into this piece in the next post)
- Performs a GET on /adfs/Proxy/GetConfiguration using the self-signed certificate to authenticate itself to the AD FS server.
- Consumes the configuration information and configures the appropriate endpoints with calls to HTTP.SYS.
So that’s the WAP side of the fence for establishing the trust. In my next post I’ll briefly cover what goes on with the AD FS server as well as examining the LDAP calls (if any) to AD DS during the registration process.
See you next time!