The general idea of this post is to list up some attack paths or scenarios where each post will outline a bunch of attack paths and it’s mitigation. It will not be the most comprehensive guidance (there are great resources to dig deeper into this than I can provide) and the solutions might not cover your needs completely. If you have an idea for improvement or a question, please reach out.
Update: For starters I will try to keep all the hardening I recommend in this post free, but I might mention options or alternatives that are available under different licenses.
Consider tooling like o365-attack-toolkit. It uses an Azure AD App registration in order to trick users into consenting to giving the attacker certain rights in the context of the user, as shown in the image below:
Users will be presented with a screen that looks like the following (courtesy of Jeff Schertz) - but usually asking for way more in terms of permissions:
Obviously we would like all users to be able to spot permissions that are a over the top and sketchy, like the ability to read a users mail, but that will not always be the case.
If you want to test how this works for yourself:
TenantId
https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize?client_id={clientId}&response_type=code&response_mode=query&scope={scopes}&state=12345&prompt=consent
tenantId
is the Azure AD tenant ID, which we made a note of earlier (or you can just grab it from the “Overview”-blade of the app registration)clientId
is the Application (client) ID, which we can find in the “Overview”-blade of the app registrationscopes
are the permissions defined under the “API-permissions”-blade, by default this is User.Read
You can also test the admin consent flow (which directly requests an admin to approve the application for the entire organization) using the following URI:
https://login.microsoftonline.com/{tenant-id|domain}/adminconsent?client_id={client-id}
The important thing for users to be vary of are scopes/permissions such as email
, offline_access
and other things that application should not normally require.
We can limit the ability for users to consent to apps, and require admin approval:
Do not allow user consent
.yes
, but it all depends on the choice made in terms of allowing users to consent to some or no apps at all.Users will now recieve a different screen, stating that you need admin approval:
All users can by default register new app registrations, so attackers can use app registrations to pivot inside the organization after gaining initial access. You can use the aforementioned o365-attack-toolkit, but now the app registration will originate from inside the organization which means the chance users click it will increase drastically.
As mentioned above, allowing users to consent to apps from verified customers also allows users to consent to app registrations from your own organization - leaving us vulnernable to this attack path.
We can limit the ability for users to create app registrations:
No
.After gaining access to an account, the first step attackers normally will do is enumerate further. Who has admin access, what groups are there, maybe some memberships are dynamic? Are there any paths to higher privileges (usually courtesy of tools like AzureHound) that we can abuse?
We can obviously not fix this entirely, but we can limit the amount of information someone with basic access can grab by default. Limiting the access to Azure AD in the Azure portal to admin users only:
Yes
.Please note that this only disables the GUI-access to the Azure Portal, so it will not affect Powershell or other types of API-access. In order to limit API and Azure Portal access we’d need to use a conditional access policy - this however is behind the Azure AD Premium P1 license.
Please also note that this CA-policy only works for Azure Powershell, not Azure AD Powershell as it uses the Graph API. Limiting access to Graph API is a bit more tricky, but we can do things like limiting the access users has to each others data by using the Set-MsolCompanySettings
-cmdlet with the -UsersPermissionToReadOtherUsersEnabled
parameter set to $false
.