AWS Managed Microsoft AD Deep Dive Part 2 – Setup

AWS Managed Microsoft AD Deep Dive  Part 2 – Setup

Today I’ll continue my deep dive into AWS Managed Microsoft AD.  In the last blog post I provided an overview of the reasons an organization would want to explore a managed service for Windows Active Directory (Windows AD).  In this post I’ll be providing an overview of my lab environment and demoing how to setup an instance of AWS Managed Microsoft AD and seamlessly joining a Windows EC2 instance.

Let’s dive right into it.

Let’s first cover what I’ll be using as a lab.  Here I’ve setup a virtual private cloud (VPC) with default tenancy which is a requirement to use AWS Managed Microsoft AD.  The VPC has four subnets configured within it named intranet1, intranet2, dmz1, and dmz2.  The subnets intranet1/dmz1 and intranet2/dmz2 provide us with our minimum of two availability zones, which is another requirement of the service.  I’ve created a route table that routes traffic destined for IP ranges outside the VPC to an Internet Gateway and applied that route table to both the intranet1 and intranet2 subnets.  This will allow me to RDP to the EC2 instances I create.  Later in the series I’ll configure VPN connectivity with my on-premises lab to demonstrate how the managed AD can be used on-prem.  Below is a simple Visio diagraming the lab.

1awsadds1.png

To create a new instance of AWS Managed Microsoft AD, I’ll be using the AWS Management Console.  After successfully logging in, I navigate to the Services menu and select the Directory Service link under the Security, Identity & Compliance section as seen below.

1awsadds2.png

The Directory Service page then loads which is a launching pad for configuration of the gamut of AWS Directory Services including AWS Cloud Directory, Simple AD, AD Connector, Amazon Cognito, and of course AWS Managed Microsoft AD.  Any directory instance that you’ve created would appear in the listing to the right.  To create a new instance I select the Set up Directory button.

1awsadds3.png

The Set up a directory page loads and I’m presented with the options to create an instance of AWS Managed Microsoft AD, Simple AD, AD Connector, or an Amazon Cognito User Pool.  Before I continue, I’ll provide the quick and dirty on the latter three options.  Simple AD is actually Samba made to emulate some of the capabilities of Windows Active Directory.  The AD Connector acts as a sort of proxy to interact with an existing Windows Active Directory.  I plan on a future blog series on that one.  Amazon Cognito is Amazon’s modern authentication solution (looks great for B2C)  providing Open ID Connect, OAuth 2.0, and SAML services to applications.  That one will warrant a future blog series as well.  For this series we’ll be select the AWS Managed Microsoft AD option and clicking the Next button.

1awsadds4.png

A new page loads where we configure the directory information.  Here I’m given the option to choose between a standard or enterprise offering of the service.  Beyond storage I’ve been unable to find or pull any specifications of the EC2 instances Amazon is managing in the background for the domain controllers.  I have to imagine Enterprise means more than just 16GB of storage and would include additional memory and CPU.  For the purposes of this series, I’ll be selecting Standard Edition.

Next I’ll provide the key configuration details for forest which includes the fully qualified domain name (FQDN) for the forest I want created as well as optionally specifying the NetBIOS name.  The Admin password set here is used for the delegated administrator account Amazon creates for the customer.  Make sure this password is securely stored, because if it’s lost Amazon has no way of recovering it.

1awsadds5.png

After clicking the Next button I’m prompted to select the virtual private cloud (VPC) I want to service deployed to.  The VPC used must include at least two subnets that are in different availability zones.  I’ll be using the intranet1 and intranet2 subnets shown in my lab diagram earlier in the post.

1awsadds6.png

The next page that loads provides the details of the instance that will be provisioned.  Once I’m satisfied the configuration is correct I select the Create Directory button to spin up the service.

1awsadds7.png

Amazon states it takes around 20 minutes or so to spin up the instance, but my experience was more like 30-45 minutes.  The main Directories Services page displays the status of the directory as Creating.  As part of this creation a new Security Group will be created which acts as a firewall for the managed domain controllers.  Unlike some organization that try to put firewalls between domain-join clients and domain controllers, Amazon has included all the necessary flows and saves  you a ton of troubleshooting with packet captures.

1awsadds8

One of the neat features offered with this service is the ability to seamlessly domain-join Windows EC2 instances during creation.  Before that feature can be leveraged an AWS Identity and Access Management (IAM) role needs to setup that has the AmazonEC2RoleforSSM attached to it.  AWS IAM is by far my favorite feature of AWS.  At a very high level, you can think of AWS IAM as being the identity service for the management of AWS resources.  It’s insanely innovative and flexible in its ability to integrate with modern authentication solutions and in how granular you can be in defining rights and permissions to AWS resources.  I could do multiple series just covering the basics (which I plan to do in the future) but to progress this entry let me briefly explain AWS IAM Roles.  Think of an AWS IAM Role as a unique security principal similar to a user but without any credentials. The role is assigned a set of rights and permissions which AWS refers to as a policy.  The role is then assumed by a human (such as federated user) or non-human (such as EC2 instance) granting the entity the rights and permissions defined in the policy attached to the role.  In this scenario the EC2 instance I create will be assuming the AmazonEC2RoleforSSM.  This role grants a number of rights and permissions within AWS’s Simple System Manager (SSM), which for your Microsoft-heavy users is a scaled down SCCM.  It requires this role to orchestrate the domain-join upon instance creation.

To create the role I’ll open back up the Services menu and select IAM from the Security, Identity & Compliance menu.

1awsadds9.png

The IAM dashboard will load which provides details as to the number of users, groups, policies, roles, and identity providers I’ve created.  From the left-hand menu I’ll select the Roles link.

1awsadds10.png

The Role page then loads and displays the Roles configured for my AWS account. Here I’ll select the Create Role button to start the role creation process.

1awsadds11.png

The Create Role page loads and prompts me to select a trusted entity type.  I’ll be using this role for EC2 instances so I’ll select the AWS service option and chose EC2 as the service that will use the role.  Once both options are selects I select the Next: Permission button.

1awsadds12.png

Next up we need to assign a policy to the role.  We can either create a new policy or select an existing one.  For seamless domain-join with AWS Managed Microsoft AD, EC2 instances must use the AmazonEC2forSSM policy.  After selecting the policy I select the Next: Review button.

1awsadds13.png

On the last page I’ll name the role, set a description, and select the Create role button. The role is then provisioned and available for use.

1awsadds14.png

Navigating back to the Directory Services page, I can see that the geekintheweeds.com instance is up and running. This means we can now create some EC2 instances and seamlessly join them to the domain.

1awsadds15.png

The EC2 instance creation is documented endless on the web, so I won’t waste time walking through it beyond showing the screenshot below which displays the options for seamless domain-join. The EC2 instance created will be named SERVER01.

1awsadds16.png

After a few minutes the instance is ready to go. I start the Remote Desktop on my client machine and attempt a connection to the EC2 instance using the Admin user and credentials I set for the AD domain.

1awsadds17.png

Low and behold I’m logged into the EC2 instance using my domain credentials!

1awsadds18.png

As you can see setup of the service and EC2 instances is extremely simple and could made that much more simple if we tossed out the GUI and leveraged cloud formation templates to seamlessly spin up entire environments at a push of a button.

We covered a lot of content in this entry so I’ll close out here.  In the next entry I’ll examine the directory structure Amazon creates including the security principals and key permissions.

See you next post!

 

Deep Dive into Azure AD Domain Services – Part 2

Deep Dive into Azure AD Domain Services  – Part 2

Welcome back to part 2 of my series on Microsoft’s managed services offering of Azure Active Directory Domain Services (AAD DS).  In my first post I covered so some of the basic configuration settings of the a default service instance.  In this post I’m going to dig a bit deeper and look at network flows, what type of secure tunnels are available for LDAPS, and examine the authentication protocols and supporting cipher suites are configured for the service.

To perform these tests I leveraged a few different tools.  For a port scanner I used Zenmap.  To examine the protocols and cipher suites supported by the LDAPS service I used a custom openssl binary running on an Ubuntu VM in Azure.  For examination of the authentication protocol support I used Samba’s smbclient running on the Ubuntu VM in combination with WinSCP for file transfer, tcpdump for packet capture, and WireShark for packet analysis.

Let’s start off with examining the open ports since it takes the least amount of effort.  To do that I start up Zenmap and set the target to one of the domain controllers (DCs) IP addresses, choose the intense profile (why not?), and hit scan.  Once the scan is complete the results are displayed.

2aad1

Navigating to the Ports / Hosts tab displays the open ports. All but one of them are straight out of the standard required ports you’d see open on a Windows Server functioning as an Active Directory DC.  An opened port 443 deserves more investigation.

2aad2.png

Let’s start with the obvious and attempt to hit the IP over an HTTPS connection but no luck there.

2aad3.png

Let’s break out Fiddler and hit it again.  If we look at the first session where we build the secure tunnel to the website we see some of the details for the certificate being used to secure the session.  Opening the TextView tab of the response shows a Subject of CN=DCaaS Fleet Dc Identity Cert – 0593c62a-e713-4e56-a1be-0ef78f1a2793.  Domain Controller-as-a-Service, I like it Microsoft.  Additionally Fiddler identifies the web platform as the Microsoft HTTP Server API (HTTP.SYS).  Microsoft has been doing a lot more that API since it’s much more lightweight than IIS.  I wanted to take a closer look at the certificate so I opened the website in Dev mode in Chrome and exported it.  The EKUs are normal for a standard use certificate and it’s self-signed and untrusted on my system.  The fact that the certificate is untrusted and Microsoft isn’t rolling it out to domain-joined members tells me whatever service is running on the port isn’t for my consumption.

So what’s running on that port?  I have no idea.  The use of the HTTP Server API and a self-signed certificate with a subject specific to the managed domain service tells me it’s providing access to some type of internal management service Microsoft is using to orchestrate the managed domain controllers.  If anyone has more info on this, I’d love to hear it.

2aad4.png

Let’s now take a look at how Microsoft did at securing LDAPS connectivity to the managed domain.  LDAPS is not enabled by default in the managed domain and needs to be configured through the Azure AD Domain Services blade per these instructions.  Oddly enough Microsoft provides an option to expose LDAPS over the Internet.  Why any sane human being would ever do this, I don’t know but we’ll cover that in a later post.

I wanted to test SSLv3 and up and I didn’t want to spend time manipulating registry entries on a Windows client so I decided to spin up an Ubuntu Server 17.10 VM in Azure.  While the Ubuntu VM was spinning up, I created a certificate to be used for LDAPS using the PowerShell command referenced in the Microsoft article and enabled LDAPS through the Azure AD Domain Services resource in the Azure Portal.  I did not enable LDAPS for the Internet for these initial tests.

After adding the certificate used by LDAPS to the trusted certificate store on the Windows Server, I opened LDP.EXE and tried establishing LDAPS connection over port 636 and we get a successful connection.

2aad5.png

Once I verified the managed domain was now supporting LDAPS connections I switched over to the Ubuntu box via an SSH session.  Ubuntu removed SSLv3 support in the OpenSSL binary that comes pre-packaged with Ubuntu so to test it I needed to build another OpenSSL binary.  Thankfully some kind soul out there on the Interwebz documented how to do exactly that without overwriting the existing version.  Before I could build a new binary I had to add re-install the Make package and add the Gnu Compiler Collection (GCC) package using the two commands below.

  • sudo apt-get install –reinstall make
  • sudo apt-get install gcc

After the two packages were installed I built the new binary using the instructions in the link, tested the command, and validated the binary now includes SSLv3.

2aad6.png

After Poodle hit the news back in 2014, Microsoft along with the rest of the tech industry advised SSLv3 be disabled.  Thankfully this basic well known vulnerability has been covered and SSLv3 is disabled.

2aad7.png

SSLv3 is disabled, but what about TLS 1.0, 1.1, and 1.2?  How about the cipher suites?  Are they aligned with NIST guidance?  To test that I used a tool named TestSSLServer by Thomas Pornin.  It’s a simple command line tool which makes cycling through the available cipher suites quick and easy.

2aad8.png

The options I chose perform the following actions:

  • -all -> Perform an “exhaustive” search across cipher suites
  • -t 1 -> Space out the connections by one second
  • -min tlsv1 -> Start with TLSv1

The command produces the output below.

TLSv1.0:
server selection: enforce server preferences
3f- (key: RSA) ECDHE_RSA_WITH_AES_256_CBC_SHA
3f- (key: RSA) ECDHE_RSA_WITH_AES_128_CBC_SHA
3f- (key: RSA) DHE_RSA_WITH_AES_256_CBC_SHA
3f- (key: RSA) DHE_RSA_WITH_AES_128_CBC_SHA
3– (key: RSA) RSA_WITH_AES_256_CBC_SHA
3– (key: RSA) RSA_WITH_AES_128_CBC_SHA
3– (key: RSA) RSA_WITH_3DES_EDE_CBC_SHA
3– (key: RSA) RSA_WITH_RC4_128_SHA
3– (key: RSA) RSA_WITH_RC4_128_MD5
TLSv1.1: idem
TLSv1.2:
server selection: enforce server preferences
3f- (key: RSA) ECDHE_RSA_WITH_AES_256_CBC_SHA384
3f- (key: RSA) ECDHE_RSA_WITH_AES_128_CBC_SHA256
3f- (key: RSA) ECDHE_RSA_WITH_AES_256_CBC_SHA
3f- (key: RSA) ECDHE_RSA_WITH_AES_128_CBC_SHA
3f- (key: RSA) DHE_RSA_WITH_AES_256_GCM_SHA384
3f- (key: RSA) DHE_RSA_WITH_AES_128_GCM_SHA256
3f- (key: RSA) DHE_RSA_WITH_AES_256_CBC_SHA
3f- (key: RSA) DHE_RSA_WITH_AES_128_CBC_SHA
3– (key: RSA) RSA_WITH_AES_256_GCM_SHA384
3– (key: RSA) RSA_WITH_AES_128_GCM_SHA256
3– (key: RSA) RSA_WITH_AES_256_CBC_SHA256
3– (key: RSA) RSA_WITH_AES_128_CBC_SHA256
3– (key: RSA) RSA_WITH_AES_256_CBC_SHA
3– (key: RSA) RSA_WITH_AES_128_CBC_SHA
3– (key: RSA) RSA_WITH_3DES_EDE_CBC_SHA
3– (key: RSA) RSA_WITH_RC4_128_SHA
3– (key: RSA) RSA_WITH_RC4_128_MD5

As can be seen from the bolded output above, Microsoft is still supporting the RC4 cipher suites in the managed domain. RC4 has been known to be a vulnerable algorithm for years now and it’s disappointing to see it still supported especially since I haven’t seen any options available to disable within the managed domain. While 3DES still has a fair amount of usage, there have been documented vulnerabilities and NIST plans to disallow it for TLS in the near future. While commercial customers may be more willing to deal with the continued use of these algorithms, government entities will not.

Let’s now jump over to Kerberos and check out what cipher suites are supported by the managed DC. For that we pull up ADUC and check the msDS-SupportedEncryptionTypes attribute of the DC’s computer object. The attribute is set to a value of 28, which is the default for Windows Server 2012 R2 DCs. In ADUC we can see that this value translates to support of the following algorithms:

• RC4_HMAC_MD5
• AES128_CTS_HMAC_SHA1
• AES256_CTS_HMAC_SHA1_96

Again we see more support for RC4 which should be a big no no in the year 2018. This is a risk that orgs using AAD DS will need to live with unless Microsoft adds some options to harden the managed DCs.

Last but not least I was curious if Microsoft had support for NTLMv1. By default Windows Server 2012 R2 supports NTLMv1 due to requirements for backwards compatibility. Microsoft has long recommended disabling NTLMv1 due to the documented issues with the security of the protocol. So has Microsoft followed their own advice in the AAD DS environment?

To check this I’m going use Samba’s smbclient package on the Ubuntu VM. I’ll use smbclient to connect to the DC’s share from the Ubuntu box using the NTLM protocol. Samba has enforced the use NTLMV2 in smbclient by default so I needed to make some modifications to the global section of the smb.conf file by adding client ntlmv2 auth = no. This option disables NTLMv2 on smbclient and will force it to use NTLMv1.

2aad9.png

After saving the changes to smb.conf I exit back to the terminal and try opening a connection with smbclient. The options I used do the following:

  • -L -> List the shares on my DC’s IP address
  • -U -> My domain user name
  • -m -> Use the SMB2 protocol

2aad10.png

While I ran the command I also did a packet capture using tcpdump which I moved over to my Windows box using WinSCP.  I then opened the capture with WireShark and navigated to the packet containing the Session Setup Request.  In the parsed capture we don’t see an NTLMv2 Response which means NTLMv1 was used to authenticate to the domain controller indicating NTLMv1 is supported by the managed domain controllers.

2aad11.png

Based upon what I’ve observed from poking around and running these tests I’m fairly confident Microsoft is using a very out-of-the-box configuration for the managed Windows Active Directory domain.  There doesn’t seem to be much of an attempt to harden the domain against some of the older and well known risks.  I don’t anticipate this offering being very appealing to organizations with strong security requirements.  Microsoft should look to offer some hardening options that would be configurable through the Azure Portal.  Those hardening options are going to need to include some type of access to the logs like I mentioned in my last post.  Anyone who has tried to rid their network of insecure cipher suites or older authentication protocols knows the importance of access to the domain controller logs to the success of that type of effort.

My next post will be the final post in this series.  I’ll cover the option Microsoft provides to expose LDAPS to the Internet (WHY OH WHY WOULD YOU DO THAT?), summarize my findings, and mention a few other interesting things I came across during the study for this series.

Thanks!

Helpful hints for resolving AD FS problems – Part 1

Hi everyone.

Over the past week I’ve been building a lab for an upcoming deep dive into Microsoft’s Web Application Proxy.  During the course of building the lab I ran into a few interesting issues with AD FS and the Web Application Proxy that I wanted to cover.  Some were similar to issues I’ve run into in production environments and some were new to me.

These issues are interesting in that there aren’t any obvious indicators of the problem in any of the typical logs.  Two out of three required some trial and error to determine root cause, while the third drove me quite insane for a good two weeks before getting an answer from an “official” source.  Over the course of this series of blogs I’ll cover each issue in detail with the hopes that it will help others troubleshoot these issues in the future.

Issue 1: AD FS Certificate authentication fails

I’m going to start with the problem that took me the longest to resolve and eventually required getting the answer directly from an official source.

For those of you that are unfamiliar, AD FS provides the capability to offer multi-factor authentication methods both native and third-party.  Out of the box, it supports certificate-based authentication as an option for a multi-factor or “step-up” authentication mechanism.

A few months back I wanted to take advantage of the certificate authentication feature to provide a two-factor authentication solution for applications integrated with AD FS.  Like a good engineer I did my Googling, read the Microsoft articles and various blogs out there to understand how the feature worked and what the requirements were.  I built a lab in Azure, setup an AD FS server, and ensured port 49443 was open in addition to the the typical ports required by AD FS.  I created my instance of AD CS, issued a user certificate containing the user’s UPN in the subject alternate name field, and setup a sample SAML app and configured it to require Certificate authentication.

How easy it all sounds right?  I navigated to the sample application and got the screen below…

Screen Shot 2017-06-04 at 9.29.35 PM

and I waited….  and waited…. and waited…  Ummm, what went wrong?  Well surely the AD FS log will tell me what happened.

Screen Shot 2017-06-04 at 9.34.03 PM.png

Well isn’t that odd.  No errors or warnings in the AD FS Admin log.  A quick check of the Application and System logs showed no errors either.  Maybe the AD FS Debug log would show me something?  I flipped on the log and attempted another authentication.

Screen Shot 2017-06-04 at 9.38.07 PM

Nothing as well?  Maybe the server can’t query the revocation lists designated in the certificates CDP?  Nope, not that either the server can successfully contact the CDP endpoints.  At this point I began to get quite frustrated and attempted packet captures, Fiddler captures, and anything and everything I could think of.  Nothing I tried revealed the answer.

I finally gave in (which I can tell you is incredibly challenging for me) and reached out to an “official” source.  We chatted back and forth and went through much of the same steps as outlined above to ensure I didn’t miss anything.  However, we ran into another dead end.  He then reached out to some other engineers he knew and eventually we got a hit.  We were told to check to see if there were any intermediary certificates stored within the trusted root certificate authorities store.  Sounds like an odd circumstance, but sure why not.

Upon opening up the certificates MMC, opening the machine store, and exploring the trusted root certificate authorities store low and behold I see an intermediary certificate within the store.  I deleted the certificate, restarted the AD FS server and attempted another login to the sample claim application and hit the screen below.

Screen Shot 2017-06-04 at 9.50.16 PM

Boom, I’m finally receiving the certificate prompt.  Clicking the OK button brings about the successful login below.

Screen Shot 2017-06-04 at 9.51.23 PM

So what was the issue?  Apparently AD FS certificate authentication fails without generating an error in any logical location (maybe nowhere at all?) if there is an intermediary certificate in the trusted root certificate authority machine store.  I’ve verified this is an issue in both AD FS 2012 R2 and AD FS 2016.  Now why this occurs is unknown to me.  It could be the underlining HTTPS.SYS driver that pukes and doesn’t report any errors to the event logs.  I didn’t get a straight answer as to why this occurs, just that it will due to some type of integrity check on the machine certificate store.  Odd right?

That completes the rundown of the first of three problems I’ll be outlining in this series of blogs.  Hopefully this helps save someone else some time and aggravation.

See you next post!

 

 

Azure AD Pass-through Authentication – How does it work? Part 2

Welcome back. Today I will be wrapping up my deep dive into Azure AD Pass-through authentication. If you haven’t already, take a read through part 1 for a background into the feature. Now let’s get to the good stuff.

I used a variety of tools to dig into the feature. Many of you will be familiar with the Sysinternals tools, WireShark, and Fiddler. The Rohitab API Monitor. This tool is extremely fun if you enjoy digging into the weeds of the libraries a process uses, the methods it calls, and the inputs and outputs. It’s a bit buggy, but check it out and give it a go.

As per usual, I built up a small lab in Azure with two Windows Server 2016 servers, one running AD DS and one running Azure AD Connect. When I installed Azure AD Connect I configured it to use pass-through authentication and to not synchronize the password. The selection of this option will the MS Azure Active Directory Application Proxy. A client certificate will also be issued to the server and is stored in the Computer Certificate store.

In order to capture the conversations and the API calls from the MS Azure Active Directory Application Proxy (ApplicationProxyConnectorService.exe) I set the service to run as SYSTEM. I then used PSEXEC to start both Fiddler and the API Monitor as SYSTEM as well. Keep in mind there is mutual authentication occurring during some of these steps between the ApplicationProxyConnectorService.exe and Azure, so the public-key client certificate will need to be copied to the following directories:

  • C:WindowsSysWOW64configsystemprofileDocumentsFiddler2
  • C:WindowsSystem32configsystemprofileDocumentsFiddler2

So with the basics of the configuration outlined, let’s cover what happens when the ApplicationProxyConnectorService.exe process is started.

  1. Using WireShark I observed the following DNS queries looking for an IP in order to connect to an endpoint for the bootstrap process of the MS AAD Application Proxy.DNS Query for TENANT ID.bootstrap.msappproxy.net
    DNS Response with CNAME of cwap-nam1-runtime.msappproxy.net
    DNS Response with CNAME of cwap-nam1-runtime-main-new.trafficmanager.net
    DNS Response with CNAME of cwap-cu-2.cloudapp.net
    DNS Response with A record of an IP
  2. Within Fiddler I observed the MS AAD Application Proxy establishing a connection to TENANT_ID.bootstrap.msappproxy.net over port 8080. It sets up a TLS 1.0 (yes TLS 1.0, tsk tsk Microsoft) session with mutual authentication. The client certificate that is used for authentication of the MS AAD Application Proxy is the certificate I mentioned above.
  3. Fiddler next displayed the MS AAD Application Proxy doing an HTTP POST of the XML content below to the ConnectorBootstrap URI. The key pieces of information provided here are the ConnectorID, MachineName, and SubscriptionID information. My best guess MS consumes this information to determine which URI to redirect the connector to and consumes some of the response information for telemetry purposes.Screen Shot 2017-04-05 at 9.37.04 PM
  4. Fiddler continues to provide details into the bootstrapping process. The MS AAD Application Proxy receives back the XML content provided below and a HTTP 307 Redirect to bootstrap.his.msappproxy.net:8080. My guess here is the process consumes this information to configure itself in preparation for interaction with the Azure Service Bus.Screen Shot 2017-04-05 at 9.37.48 PM
  5. WireShark captured the DNS queries below resolving the IP for the host the process was redirected to in the previous step.DNS Query for bootstrap.his.msappproxy.net
    DNS Response with CNAME of his-nam1-runtime-main.trafficmanager.net
    DNS Response with CNAME of his-eus-1.cloudapp.net
    DNS Response with A record of 104.211.32.215
  6. Back to Fiddler I observed the connection to bootstrap.his.msappproxy.net over port 8080 and setup of a TLS 1.0 session with mutual authentication using the client certificate again. The process does an HTTP POST of the XML content  below to the URI of ConnectorBootstrap?his_su=NAM1. More than likely this his_su variable was determined from the initial bootstrap to the tenant ID endpoint. The key pieces of information here are the ConnectorID, SubscriptionID, and telemetry information.
    Screen-Shot-2017-04-05-at-9.35.52-PM
  7. The next session capture shows the process received back the XML response below. The key pieces of content relevant here are within the SignalingListenerEndpointSettings section.. Interesting pieces of information here are:
    • Name – his-nam1-eus1/TENANTID_CONNECTORID
    • Namespace – his-nam1-eus1
    • ServicePath – TENANTID_UNIQUEIDENTIFIER
    • SharedAccessKey

    This information is used by the MS AAD Application Proxy to establish listeners to two separate service endpoints at the Azure Service Bus. The proxy uses the SharedAccessKeys to authenticate to authenticate to the endpoints. It will eventually use the relay service offered by the Azure Service Bus.

    Screen Shot 2017-04-05 at 9.34.43 PM

  8. WireShark captured the DNS queries below resolving the IP for the service bus endpoint provided above. This query is performed twice in order to set up the two separate tunnels to receive relays.DNS Query for his-nam1-eus1.servicebus.windows.net
    DNS Response with CNAME of ns-sb2-prod-bl3-009.cloudapp.net
    DNS Response with IP

    DNS Query for his-nam1-eus1.servicebus.windows.net
    DNS Response with CNAME of ns-sb2-prod-dm2-009.cloudapp.net
    DNS Response with different IP

  9. The MS AAD Application Proxy establishes connections with the two IPs received from above. These connections are established to port 5671. These two connections establish the MS AAD Application Proxy as a listener service with the Azure Service Bus to consume the relay services.
  10. At this point the MS AAD Application Proxy has connected to the Azure Service Bus to the his-nam1-cus1 namespace as a listener and is in the listen state. It’s prepared to receive requests from Azure AD (the sender), for verifications of authentication. We’ll cover this conversation a bit in the next few steps.When a synchronized user in the journeyofthegeek.com tenant accesses the Azure login screen and plugs in a set of credentials, Azure AD (the sender) connects to the relay and submits the authentication request. Like the initial MS AAD Application Proxy connection to the Azure Relay service, I was unable to capture the transactions in Fiddler. However, I was able to some of the conversation with API Monitor.

    I pieced this conversation together by reviewing API calls to the ncryptsslp.dll and looking at the output for the BCryptDecrypt method and input for the BCryptEncrypt method. While the data is ugly and the listeners have already been setup, we’re able to observe some of the conversation that occurs when the sender (Azure AD) sends messages to the listener (MS AAD Application Proxy) via the service (Azure Relay). Based upon what I was able to decrypt, it seems like one-way asynchronous communication where the MS AAD Application Proxy listens receives messages from Azure AD.

    Screen Shot 2017-04-05 at 9.38.40 PM

  11. The LogonUserW method is called from CLR.DLL and the user’s user account name, domain, and password is plugged. Upon a successful return and the authentication is valided, the MS AAD Application Proxy initiates an HTTP POST to
    his-eus-1.connector.his.msappproxy.net:10101/subscriber/connection?requestId=UNIQUEREQUESTID. The post contains a base64 encoded JWT with the information below. Unfortunately I was unable to decode the bytestream, so I can only guess what’s contained in there.{“JsonBytes”:[bytestream],”PrimarySignature”:[bytestream],”SecondarySignature”:null}

So what did we learn? Well we know that the Azure AD Pass-through authentication uses multiple Microsoft components including the MS AAD Application Proxy, Azure Service Bus (Relay), Azure AD, and Active Directory Domain Services. The authentication request is exchanged between Azure AD and the ApplicationProxyConnectorService.exe process running on the on-premises server via relay function of the Azure Service Bus.

The ApplicationProxyConnectorService.exe process authenticates to the URI where the bootstrap process occurs using a client certificate. After bootstrap the ApplicationProxyConnectorService.exe process obtains the shared access keys it will use to establish itself as a listener to the appropriate namespace in the Azure Relay. The process then establishes connection with the relay as a listener and waits for messages from Azure AD. When these messages are received, at the least the user’s password is encrypted with the public key of the client certificate (other data may be as well but I didn’t observe that).

When the messages are decrypted, the username, domain, and password is extracted and used to authenticate against AD DS. If the authentication is successful, a message is delivered back to Azure AD via the MS AAD Application Proxy service running in Azure.

Neato right? There are lots of moving parts behind this solution, but the finesse in which they’re integrated and executed make them practically invisible to the consumer. This is a solid out of the box solution and I can see why Microsoft markets in the way it does. I do have concerns that the solution is a bit of a black box and that companies leveraging it may not understand how troubleshoot issues that occur with it, but I guess that’s what Premier Services and Consulting Service is for right Microsoft? 🙂