Locking down Azure AD, a closer look at the value proposition


Microsoft does not yet provide fine-grain access controls for Azure Active Directory. This is in stark contrast with Active Directory Domain Services, which shipped in 2000 with Windows Server 2000, where you can restrict access down to the individual attribute on an object.

Microsoft has been investing heavily in improving the role-based access controls (RBAC) infrastructure underlying Azure Active Directory, but to date, the features provided have primarily focused on reducing the number of people in the global admins role–a role which can do just about anything in your Azure AD tenant.

If you want to limit access to the data in Azure AD, you have only a few options:

  1. Don’t put it in Azure AD. We exercise this option with course groups and other groups whose membership is considered confidential. This is in stark contrast with our Active Directory, where the fine-grain access controls available allow us to include course groups.
  2. Obscure data in Azure AD. With this solution, we change the real data to avoid undesired consequences of that data being generally available.
  3. Only allow a limited number of users & apps to have read permissions to anything. This option puts you in the role of gatekeeper for any scenario which requires read access to objects in your Azure AD, i.e. it introduces a huge amount of friction, which can only lead to less interest and use of Azure AD based technologies. This includes owners of Azure subscriptions, 3rd party applications trying to do low-risk OAuth activities, and IT professionals trying to get their job done. Many folks with perfectly good business intentions who run into the problems this creates will give up.


It’s worth noting that there are a couple special purpose solutions that Microsoft has created, e.g. by default guest users can only see their own account and nothing else in your Azure AD tenant. This special purpose solution suggests that Microsoft has the capability to implement fine-grain access control solutions but hasn’t yet prioritized the ability for customers to craft custom solutions which meet their own purposes.

Solution #1 – don’t put data in Azure AD

Solution #1 is not really a solution–it’s a dodge. If you avoid putting data in Azure AD, you aren’t getting the value Azure AD might provide.

Everyone loses with this solution–there is no value–just avoiding the bad outcomes associated with data being exposed.

Solution #2 – obscure data in Azure AD

With this solution, we change the real data to avoid undesired consequences of that data being generally available. The scenarios where this type of solution are most appropriate are not unique to Azure AD–they usually involve obscuring the data at the source system, and informing those who consume that data with ways to decode that presented information. An example might be a person’s name, where a person at risk has a different name presented than their actual name.

This type of solution generally is best when implemented at the source system and the affected parties have consented to the solution–not in or at the boundary of Azure AD. When implemented on a per-system basis like only in Azure AD, you set up a paradigm where one system has false data but others do not. This paradigm will create support overhead and disincentive to use that system.

This solution is only valuable for specific, limited use cases, not for generally solving Azure AD access control limitations.

Solution #3 – Conditional Access generally prevents read access via undocumented option

Solution #3 is predicated on limiting access to the user interfaces that can be used to query Azure AD information. By blocking the UIs, you block access to the data. You probably already saw the problem–what if a new UI shows up? This solution is predicated on rocky ground which assumes Microsoft won’t introduce something new–which in this constantly changing environment is absolutely not a safe bet.

You implement solution #3 by implementing a Conditional Access policy that prevents issuing access tokens (OAuth) to the Azure Management application in your tenant. Microsoft has never documented what the Azure Management application actually represents. So by implementing this policy you are taking an unknown risk that essentially says:

  • I’m able to determine all the impacts myself
  • Microsoft won’t change what this means on me
  • I will identify all the valid business reasons for a user/application to have access beyond themselves and manually manage exceptions to this policy
  • The chilling effect this policy will have is an acceptable cost

To dig a bit deeper on this, based on other customer reports it is believed that Azure Management includes the following:

  • Azure Portal (portal.azure.com)
  • Office Portal (portal.office.com)
  • Azure AD Graph API
  • Microsoft Graph API
  • PowerShell modules which interact with Azure AD, including but not limited to:
    • MSOnline
    • AzureAD

Whether there are additional affected interfaces is unknown.

The most widely used of these interfaces is the Azure Portal. A customer would have to identify all subscriptions in their tenant, and for each subscription, identify the owners or other role holders which might need to access the Azure Portal, and have some acceptance process to allow them to be excluded from the Conditional Access policy which blocked access to Azure Management.

Similar mitigation steps would be needed for the other capabilities included in Azure Management. Of the others, the hardest to address would be 3rd party applications with OAuth permissions. These applications operate on a consent basis–if a user grants consent, they are allowed to read designated information about the user. The Conditional Access policy would block such 3rd party applications from retrieving that data, unless they were excluded. Depending on how this was approached, this has the potential to recreate a gatekeeper situation for Azure AD applications. At the University of Washington, we spent several years in contention over a gatekeeper approach to Azure AD applications, and reverting the progress made is undesirable.

A problem with this approach is that it won’t necessarily entirely lock down access to the data you’ve put in Azure AD. Some of Microsoft’s applications (which they sometimes call 1st party applications) have been granted broad read access to a variety of data in your Azure AD. For example, Exchange Online can read a lot of Azure AD based data. To really be effective, you’d also need to analyze every one of these Microsoft applications for whether it exposed data and then mitigate those issues, if you can. In some cases, you may find that you can’t mitigate the behavior of an application which Microsoft controls other than to stop using that application. If the application were Exchange Online, not many organizations would seriously consider stopping use of Exchange Online.

The initial effort of implementing solution #3, without also analyzing and mitigating all 1st party Microsoft applications, is estimated at 200 hours. Ongoing maintenance is estimated at 2h/week. Additionally analyzing 1st party Microsoft applications is likely to add at least 600 hours to the effort.


While you could implement a Conditional Access policy, the consequences of doing so are broad and would require significant effort to implement in a well-planned manner. There are chilling effects and other unknown costs. For these reasons, unless the need is very significant, this solution is not recommended.

Bloodhound – AD Attack Resilience Methodology

Last month I was introduced to BloodHound and the Active Directory Adversary Resilience Methodology via a special workshop put on by SpecterOps.

While a lot of the time and technical nit-picky details center on the Cypher query language, the overall technology and approach is so awesome that I found myself not really caring that it took awhile to figure out how to express what I wanted.

Here’s the punch-line: as a defender, with this approach you have a really excellent tool to figure out how attackers might compromise the high-value targets protected by your Active Directory. This includes a visual map of their potential path, and a way to model how possible mitigations might change what paths are left. The tool itself has an excellent command of the possible exposures in an AD environment–which I can almost guarantee will exceed your awareness and ability to track within your environment.

With a tool and approach like this, you can:

  • identify weak points in your environment which need extra attention
  • have a quantitative way to evaluate possible mitigations or changes proposed
  • quantitatively compare your security posture between two points in time

The tool is not perfect, but for something that is an open-source labor of love that has been released in the last year–it’s pretty impressive–especially when you note the scientific methodology behind the tool.

Here’s how it generally works:

  1. You setup a neo4j database (and web interface) – https://www.youtube.com/watch?v=o22EMEUbrNk (walkthrough)
  2. You setup bloodhound to use that neo4j db – https://github.com/BloodHoundAD/BloodHound/releases/tag/2.0.3 (check for newer versions)
  3. You run bloodhound’s data collector in your environment to populate bloodhound’s db (look for smarthound in the above repo)
  4. You use a combination of the bloodhound UI and the neo4j web interface to explore your environment and the possible attack paths

Neo4j is a graph database, with nodes and edges (relationships between nodes). This allows the modeling needed to happen in an efficient way. Bloodhound defines a great set of AD related nodes and edges in its schema, and the data collector goes about discovering that data in your environment.

Once you’ve got a database with data from your environment, you can use the bloodhound UI or the neo4j web interface (using the cypher query language) to identify attack paths to high-value targets in your environment. A very obvious path you might want to find are ways to go from domain users to domain admins. Finding all such paths in a single query isn’t really practical–instead you might find all paths which are the shortest in terms of the number of hops from node to node. For example, a domain user might be able to log into a computer where a domain admin has a session (i.e. has logged in)–that’s a short path to escalate to domain admin.

You have the power to manually manipulate the nodes and edges in the database. You can add nodes or edges. You can remove nodes or edges. You might do this to simulate what the environment would look like if you applied that mitigation in your real environment.

By iteratively applying manual manipulations and re-running queries for the shortest attack paths you can identify as many weak points in your environment as you care to find. This gives you a laboratory-like environment where you can explore and test a hypothesis using a scientific methodology.

If you layer an analysis tool like PowerBI on top of this, you can put together a dashboard which gives you an objective sense of the overall security stance of your environment in a potential configuration. You’d applying manual manipulations to your bloodhound database and check the PowerBI dashboard to see how much improvement resulted. Likewise, you might use this kind of approach to provide an independent analysis of the security risk profile to any proposed change in your environment before it actually is implemented.

There are some approaches you’ll need to figure out if you use bloodhound as a risk evaluation tool.

Database management

If you are making manual changes, you are likely to want some way to copy and roll-back your database to the a given state. Alternatively, you can save your sharphound data collection and re-import to a fresh database. Do you need multiple copies of the database to support more than one purpose?

Data collection

How often do you do a fresh run of sharphound? And import it?
Which account runs sharphound? From which host(s) is sharphound run?
Do you notify others in your environment that they may see connections from the sharphound host(s)?

Basic reading


Intermediate reading

Sharphound rewrite: https://blog.cptjesus.com/posts/newbloodhoundingestor
Low-level technical details on sharphound: https://blog.cptjesus.com/posts/sharphoundtechnical
Intro to Cypher: https://blog.cptjesus.com/posts/introtocypher
Cypher cheat sheet: https://neo4j.com/docs/cypher-refcard/current/


Slack channel for Bloodhound: https://bloodhoundgang.herokuapp.com/


Andy Robbins Twitter: @_wald0
Rohan Vazarkar Twitter: @CptJesus

Azure AD Roles

I’ve been exploring AAD roles, but there’s a lot left unexplained by Microsoft. This is a bit of discovery, via stream of consciousness which hopefully will be helpful to others.

The general task I’m looking at is finding out all possible AAD roles and the membership of each. This task is not as straightforward as it seems. For one, the various interfaces to AAD don’t agree on what the AAD roles are. None of the GUI interfaces give you a way to discover who is in a role. When I run into ‘can’t do that with the GUI’, I generally turn to Graph because then I get full details. Yes, there are ways to approach this with PowerShell, but I note that it also doesn’t list a couple of the possible roles.

Via Graph, there are role template objects and role objects. You can find out the members of a given role by querying graph (https://msdn.microsoft.com/en-us/Library/Azure/Ad/Graph/api/directoryroles-operations). However, I note that in Graph, there is not alignment between the role objects and the superset of roles listed in the GUI interfaces (nor with a list presented to MVPs as ‘recently released’). The missing role objects are present as role template objects (and even the list of “roles coming soon” are present as role template objects).

This left me wondering … how do those role objects get created? Is my tenant out of expected state because some Microsoft task failed or hasn’t reached my tenant yet? Or is there a ‘just in time’ provisioning of role objects when the first user is assigned to them? Or is there some step a tenant is expected to do to activate a role?

Aha. I partially see now. Graph documentation says that I have to activate directory roles from newly added templates. https://msdn.microsoft.com/en-us/Library/Azure/Ad/Graph/api/directoryroles-operations#ActivateDirectoryRole

However, the general documentation about roles https://docs.microsoft.com/en-us/azure/active-directory/active-directory-assign-admin-roles doesn’t mention this, whereas the developer documentation for Graph does … this makes me wonder if it might be both of the possibilities I mentioned. In other words, if you are using graph to do role assignment you must manually activate roles, but if you are using the GUI interfaces or PowerShell cmdlets, it silently does that for you via a just-in-time creation of the role object. Is that accurate?

I also wonder what controls which roles are present in each of the various interface’s experience—heck, let’s get really specific and talk specifically about the new Azure portal. Why does the new Azure portal not list every possible role in my tenant?

I wonder about these role templates which are present in my tenant Microsoft told MVPs aren’t yet released. What happens if I activate one of them now? If there is a downside to doing that, how is a tenant admin expected to know that a given role template isn’t ready?

I got around to testing the AzureAD PS module. When you combine the two cmdlets it provides, it returns more roles than the MSOnline module. Its approach follows the AAD Graph object types.

The MSOnline PS module seems to return roles which are both a role object and a role template object, minus a couple. 🙁

The AzureAD PS module cmdlets returns the AAD objects they are named for. So get-azureAdDirectoryRole returns only roles which are a role object, and get-azureAdDirectoryRoleTemplate returns role template objects.

The output of get-azureAdDirectoryRoleTemplate does not match the output of the MSOnline get-msolrole. The difference is that get-azureAdDirectoryRoleTemplate has a couple additional roles:

  • Mailbox Administrator
  • User
  • Email Verified User Creator
  • Adhoc License Administrator

This gives me greater confidence in the AzureAD PS module than the MSOnline PS module.

Lacking verification from Microsoft, I think my hypothesis that some of the tools do just-in-time activation of role templates (i.e. create a role object based on the template) and some require you to do that yourself seems to fit what I can see. I’m still left wondering what happens if you activate a role template that Microsoft has added to your tenant but not said was “released”.


Gaps I see that Microsoft might want to address:

  • *Should* document that some roles can only be provisioned via some tools
  • *Should* be more accessible listing of all the possible roles—the fact that you have to use either Graph or a non-GA PS module to get that info comprehensively is not a good state of affairs
  • Might want to talk more about role activation in IT Pro documentation
  • Depending on whether some role templates that are deployed are dangerous or not, there should be some definitive list of released roles, or an attribute on the role template that says whether it is usable, or even something at the Graph layer that blocks certain templates from being activated until they are ready. I haven’t dived very deep on this topic, so there is some ambiguity on this that I might explore further by trying to activate some of those roles that aren’t yet “released”.
  • Deeper documentation on role assignments.
  • What objects can be assigned? I see users and servicePrincipals, and I think I heard that groups can be assigned. What else? Put it in the documentation.
  • Sub-delegation of roles. When a servicePrincipal is a role holder there is some ambiguity about who has the permissions associated with that role. For example, the ‘Office 365 Service Trust Portal’ is a “Directory Writer’ in any tenant with O365 in it. I presume that some of the roles defined by that AAD application  sub-delegate some portions of the ‘Directory Writer’ role out. The point here is calling attention to the fact that when a servicePrincipal has a role, you are extending some trust to users of that AAD app. Documentation should call this out.

Note: A specific example that I’m worried about is the ‘Microsoft Power BI Information Service’ servicePrincipal having been added as a Global Admin (I presume by Microsoft). That seems like an extreme amount of permissions and assuming Microsoft added it is a bit of a violation of Azure first principles (you own your own tenant). I haven’t dug into that one via the Audit API to find out who/when it was added, but it is on my list to investigate further.


Managing Azure AD Applications

About 10 months ago, it came to my attention that there was a fundamental problem related to Azure AD and applications.

This was a surprise to me–I had cheered on the product team manifesto that applications were first-class citizens in Azure AD.

Since then, I’ve been on a journey of discovery and advocacy. My journey eventually led me to talking with several PMs on the Azure AD product team.

I’ve learned that there is a lot about Azure AD applications and the AAD settings governing them that is poorly documented. I’ve encouraged the product team to fill the documentation gap, and amend the design to provide the right access controls. That journey still continues, and I’m here now to share what I know.

First, I’ll call your attention to the published documentation and relevant links related to the topic of AAD and applications.

The Application object vs. ServicePrincipal document is important in that provides some key understanding if you want to go about identifying all the applications in your AAD tenant. You won’t find all of your AAD applications in *any* of the GUI interfaces, such as the Azure Management Portal or the AAD Access Panel. This omission of some AAD applications in the GUI interfaces is unfortunate because it makes it harder to understand what’s really going on specific to your tenant. You can use the MSOnline Powershell module or the AAD Graph API to discover all of your AAD applications.

The Consent framework document is useful, but it’s one of the documents which is flawed in my opinion–it is incredibly misleading about reality. The reality is that only a fraction of your AAD apps allow user consent–all the others *assume* that the user consent is unnecessary. To my way of thinking, this is a significant design flaw, and the documentation isn’t doing anyone favors by not pointing out that not all apps are subject to user consent.

This brings me to the heart of the new information I have to share. The first link above likely isn’t known to you–it reveals some behind-the-scenes details that aren’t revealed elsewhere, and documents published in that platform are harder to find for some reason. Note that every AAD application has a “home” tenant. Some are enabled for multiple tenancy and some aren’t.

Note that some applications are “curated” by Microsoft–these are the pre-integrated applications in the Azure AD App Gallery. These pre-integrated applications live in a special tenant that Microsoft owns/runs.

Note that there are some applications “owned” by Microsoft–these are applications like Sharepoint Online. It turns out that these applications are “special” in that they are automatically deployed to *every* AAD tenant without any explicit acceptance on your part.

And then there are the applications that anyone might create/develop. These applications fall into two sub-categories:

  • Those that are only in your tenant–one of your users adds them. Microsoft sometimes uses the code words “line of business” apps to refer to these.
  • Those which live in some other tenant and have been added to work with your tenant. Microsoft has two different nicknames for these: consented apps or multi-tenant apps.

It turns out that the only type of AAD app which permits user consent are that sub-category with the consented app nickname.

Down below is a handy reference table I put together while interacting with the AAD PMs that own each of these different AAD app categories that includes all of these details.

Moving beyond the documentation gap and the user consent design flaw, there are several other fundamental problems.

One problem I implied above–that Microsoft can deploy applications to your tenant without notice or consent. I think this assumption on Microsoft’s part is very problematic and I’d encourage them to rethink it and provide enterprise controls for each app they would like to deploy. This is problematic because it violates the design principle that we own our Azure properties. I do not want Bing for Business published to my users–or the latest app that Microsoft has created but which has no HIPAA and BAA agreement. Putting such an application in front of my users will lead to regulatory problems, and is a significant deal breaker. Microsoft’s hubris in thinking they know my environment or that they can use a captive audience to instantly gain market share for their latest creation is ultimately not good for their long-term business relationship with their customer. They need to provide a control here.

Another is in the lack of controls Microsoft has provided around application permissions. OAuth is really cool–it is the protocol Microsoft has adopted that allows one application to be given permissions to another. But Microsoft hasn’t provided the right controls to manage these permissions. Here’s how things work: a developer somewhere writes an application. That developer decides which application permissions their application needs. That developer publishes their application so it is multiple tenant aware. Someone in your tenant comes along and decides to add that application. In the current state, that decision to add the application is an acceptance that the application permissions are acceptable. For many of the types of AAD applications, the person adding the application has no understanding of the implications nor responsibility in your organization for the consequences. A better design would involve a workflow where individuals with specific roles had to approve any application that asked for certain application permissions. Global admins should be required to approve any application that requires the ability to query AAD. Exchange Online admins should be required to approve any application that requires the ability to query Exchange Online. And so on. In the absence of this kind of design, Microsoft needs a stop-gap where it notifies global admins that an application has been added which grants permissions to high-value and high-risk applications like AAD and the set of O365 applications.

Another problem in this area is the poor presentation and documentation specific to the AAD tenant application settings. The Configure tab in the AAD section of the Azure Management Portal has two settings under an “integrated applications” heading.


The names of these settings imply something very different from reality. If you set the first one to yes, you’d think that users can consent to all applications now. And if you set the second one to no, you’d think that no users can add applications. In both cases, you’d be wrong. What’s worse is that if you try to educate yourself by following the help link for these settings, you are sent to a useless AAD product “marketing” page which doesn’t tell you anything about Azure AD applications at all. Of course, there is no Microsoft documentation which informs you that what these settings claim to do isn’t really possible.

To the best of my knowledge, here is what those two settings really mean:

Users may give applications permission to access their data

If the AAD app is a multi-tenant application which is neither a Microsoft nor AAD App Gallery application, then user consent to access their data is possible with that application . The data might be in any number of other AAD applications, including Azure AD itself.

Note that some applications have no user consent or explicit admin consent whatsoever.

Users may add integrated applications

If this setting is yes, then any user in your tenant can add a developed application whether it is a consented/multi-tenant application or a “line of business”/single tenant application. If this setting is no, then only global admins can add these kinds of applications.

Note that if users can add applications, there is no enterprise controls for which data a given application can access. The only control in this case is the user.

A Reference Table for different types of Azure AD Applications

Here’s a handy reference table for keeping things straight: