Recreating Malicious login in Azure AD - azure

We had a user's creds exposed and a threat actor used them to successfully log in to Azure CLI with the user's creds.
We've since resolved the access issue using conditional access and our MFA (which admittedly was a hole).
I'm trying to recreate the method of attack though and I can't seem to get it right.
Here is the activity details for the malicious sign-in:
Application
Microsoft Azure CLI
Application ID
04b07795-8ddb-461a-bbee-02f9e1bf7b46
Resource
Windows Azure Service Management API
Resource ID
797f4846-ba00-4fd7-ba43-dac1f8f63013
Resource tenant ID
LEft out
Home tenant ID
Left out
Home tenant name
Client app
Mobile Apps and Desktop clients
Client credential type
None
Service principal ID
Service principal name
Resource service principal ID
d2b4c9e3-9a2a-4360-8ba4-6ece086335c5
Unique token identifier
Left Out
Token issuer type
Azure AD
Token issuer name
Incoming token type
None
Authentication Protocol
ROPC
Latency
90ms
Flagged for review
No
User agent
Looks like they used ROPC detailed here https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc
I've tried emulating it through Azure CLI directly but it doesn't report back "ROPC" as authentication. So they are definitely calling through ROPC.
Then I tried emulating it with my creds in Postman and I get almost the same result as above in the sign-in log:
Application
Microsoft Azure CLI
Application ID
04b07795-8ddb-461a-bbee-02f9e1bf7b46
Resource
Microsoft Graph
Resource ID
00000003-0000-0000-c000-000000000000
Resource tenant ID
Left out
Home tenant ID
Left out
Home tenant name
Client app
Mobile Apps and Desktop clients
Client credential type
None
Service principal ID
Service principal name
Resource service principal ID
e10569b0-24e4-4495-9d9b-698b01290eae
Unique token identifier
Left out
Token issuer type
Azure AD
Token issuer name
Incoming token type
None
Authentication Protocol
ROPC
Latency
108ms
Flagged for review
No
User agent
PostmanRuntime/7.30.0
As you can see it's very similar, but mine is reporting "Microsoft Graph" while the malicious entry reports Windows Azure Service Management API.
Can someone point me in the right direction?

Windows Azure Service Management API refers to the Azure Resource management API.
I tried checking Sign in Logs and the Service Principal Sign In’ Logs has Windows Azure Service Management API refer here :-
Note- The above sign in log is of the Service principal sign in with
Client credentials flow. You can find that Service principal by
copying its Application ID and pasting it in app registrations page or
enterprise application page of Azure AD.
I tried to log in to Azure with service principal named Powershell with ROPC Flow via Postman
Received Access token like below :-
Called Graph API
Got resource as Microsoft Graph in Sign in Logs similar to you:-
Now, I tried calling Azure Resource management API to get list of Azure resources from my account with the same Flow and got the Resource set to Windows Azure Service Management API like below :-
Added Azure Service Management API permissions:
Now, I changed the scope to https://management.azure.com/default like below:
Fetch the access token from above call and ran below query to get list of resources:
When I checked sign in logs now, it’s showing ROPC with Windows Azure Service Management API resource like below:

Related

How do I use the azure msal library to access azure service management apis?

All of the examples on the microsoft azure site having to do with a client application or a service principal having access to azure apis all show the graph apis as the example.
I got those to work, but what I need to do is access the azure service management apis.
If I take an auth token that works for the graph api and use it for the service management api, I get an "Authentication failed." error.
I have added the api permission for "azure service management" and the user_impersonation delegated permission type to my public client app, but the management apis still fail.
Am I going about this all wrong?
I get the idea that the service management apis are authenticated a different way since there's absolutely no mention of using them anywhere in any of the auth examples.
I suppose you are using the client application or a service principal to access azure resources. If so, you are using the client credential flow, but the user_impersonation of Azure Service Management API is a delegated permission, it will not take effect in this flow.
The permission is used to be consent by the user who login to the AD App e.g. in the auth code flow, when it has been consent by the user, the App will be able to represent the user to access the azure resources, note the permission is from the user, not the app. So if you want to use this flow, the user should have a role in the subscription or specific resources.
To access the azure resources with the client application or a service principal, you just need to add the service principal as an RBAC role in the Access control (IAM) of your subscription or specific resource, no need to add any API permission in Azure AD, see this link. Then the service principal will be able to access the azure resources.
When you getting the token to access the azure resources, e.g. call the REST APIs, the scope should be https://management.azure.com/.default, not the https://graph.microsoft.com/.default, you can just get the token for one resource in one time.

Login from Microsoft account not working for Multitenant Azure AD application

I'm building multitenant SaaS web based application. Application is registered in my tenant and each customer with their office 365 subscription will get Service principal object in Azure AD.
I'm having problem with login from external account (Microsoft account) in customer tenant.
I created example and tried to see what I can get from access token.
Sample consists from one client application (.js) that uses MSAL library to handle authentication and two APIs that have protected endpoints. I also created three separate Azure AD applications AlanClient, AlanAPI1, AlanAPI2. Both AlanAPI1 and AlanAPI2 have API exposed (Expose an API section in Azure Portal application) and have specified one consumer AlanClient. AlanClient has permission to both APIs. All applications are registered with "accessTokenAcceptedVersion": 2 and "signInAudience": "AzureADMultipleOrgs".
As far as I understood this should be enough to login with
Office 365 account from host tenant
Microsoft account that is registered as external user in host tenant
Office 365 account from guest tenant
Microsoft account that is registered as external user in guest tenant
Clarification:
- host tenant --> Azure AD instance in which application is registered. In error message bellow tenant A.
- guest tenant --> Azure AD instance that is only using application
I have a problem with case no. 4
I get this error message:
AADSTS50020: User account 'lovro.p365#...' from identity provider 'live.com' does not exist in tenant 'A' and cannot access the application AlanClient in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure AD user account.
The scenes of 2 and 4 should be the same.
I have tested both and everything is OK.
You could use OAuth 2.0 auth code grant flow to have a test with it.
Construct a request to login.microsoftonline.com with your app configurations.
This URL will look like:
https://login.microsoftonline.com/[tenant A]/oauth2/v2.0/authorize?client_id=[client id of the Azure AD app registered in host tenant]&response_type=code&redirect_uri=[redirect uri of the Azure AD app]&nonce=1234&resource=https://graph.microsoft.com.
After signing in with credentials of Microsoft Account in tenant A, you will get a "code" in the address bar. Use this code to request access token:
POST /[tenant]/oauth2/v2.0/token HTTP/1.1
client_id=[client id of the Azure AD app registered in host tenant]
&scope=https://graph.microsoft.com/user.read
&code=[code got from the previous step]
&redirect_uri=[redirect uri of the Azure AD app]
&grant_type=authorization_code
Then we could get the access token for Microsoft Account as a guest user in tenant A.

Credentials prompt for access to Azure management APIs

I've been using the Azure fluent management APIs (https://github.com/Azure/azure-libraries-for-net) with some success in .NET Core.
However, I want to prompt the user to enter some credentials for a Microsoft account. Those credentials would have access to one or more Azure tenants / subscriptions, so I'd like to be able to use the result to browse and manage resources there.
This is something very close to what I would believe Azure Data Studio does: you can enter some Azure creds, and your resources will appear in the app.
I'm trying to understand the best approach for this. There seem to be a billion sites out there when you talk about Azure AD app registrations, but I haven't found a fruitful specific search query yet. I know I can register an app, get a client ID and client secret. I know I can set it to be usable by organisational accounts in the current tenant, or all tenants.
I can add the "Azure Service Management (delegated permissions : user_impersonation)" permission to my API permissions section for the app, but what's next?
If I use Microsoft.Identity.Client (as in https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-netcore-daemon), I run into some questions:
AcquireTokenForClientAsync doesn't prompt the user - I guess because it's getting a token for the app to act with its own permissions?
AcquireTokenOnBehalfOfAsync wants a JWT.. great! I'll pass the one I got from AcquireTokenForClientAsync! Nope, AADSTS70002: Error validating credentials. AADSTS500137: The token issuer doesn't match the api version: A version 1 token cannot be used with the v2 endpoint.
I don't know what scope I want. https://management.azure.com/user_impersonation is apparently invalid.. https://management.azure.com/.default works, but is that right? It's a guess, combo of the former and a .default suffix I found for Graph API scopes online. Any docs on this?
I ultimately get a JWT and tenant ID back. I can't find a way to use a JWT with the Fluent management APIs.. and my account (for instance) is associated with 3 tenants or 5 different tenants / directories - so how do I choose?
That's just what I've tried, the appropriate route might be a different one. In summary: I want a .NET Core Console app to request user credentials, and then get access to the Azure resources they have access to, in order to perform some resource management.
AcquireTokenForClientAsync doesn't prompt the user - I guess because it's getting a token for the app to act with its own permissions?
You are using the OAuth 2.0 client credentials grant to access web-hosted resources by using the identity of an application. This type of grant commonly is used for server-to-server interactions that must run in the background, without immediate interaction with a user .
AADSTS70002: Error validating credentials. AADSTS500137: The token issuer doesn't match the api version: A version 1 token cannot be used with the v2 endpoint.
Azure AD provide two service : Azure AD V1.0 and Azure AD V2.0 . Please refer to Comparing the Azure AD v2.0 endpoint with the v1.0 endpoint . You can't use v1 token to acquire v2's token in a on-behalf-of flow .
AcquireTokenOnBehalfOfAsync wants a JWT.. great! I'll pass the one I got from AcquireTokenForClientAsync
AS pointed above , That function is used to acquire an access token for this application (usually a Web API) from the authority configured in the application, in order to access another downstream protected Web API on behalf of a user using the OAuth 2.0 On-Behalf-Of flow. So you can't use app token which acquire using Client Credential flow .
https://management.azure.com/.default works, but is that right? It's a guess, combo of the former and a .default suffix I found for Graph API scopes online. Any docs on this?
You are using the Azure Active Directory v2.0 and the OAuth 2.0 client credentials flow , when sending a POST request to the /token v2.0 endpoint ,the scope should be :
The value passed for the scope parameter in this request should be the resource identifier (Application ID URI) of the resource you want, affixed with the .default suffix. For the Microsoft Graph example, the value is https://graph.microsoft.com/.default. This value informs the v2.0 endpoint that of all the direct application permissions you have configured for your app, it should issue a token for the ones associated with the resource you want to use.
Please check the Get a tokensection in above document .
I ultimately get a JWT and tenant ID back. I can't find a way to use a JWT with the Fluent management APIs..
AFAIK , currently Azure AD V2.0 apps can use:
Its own API
Microsoft Outlook APIs
Microsoft Graph API
Azure AD V2.0 currently doesn't support Azure management APIs .
So you problem is you need to allows work and school accounts from Azure AD and personal Microsoft accounts (MSA) which works with Azure AD V2.0 , but you can't use Azure management APIs . You can use Azure management APIs in Azure AD V1.0 but it allows only work and school accounts to sign in to your application , unless you invite Microsoft accounts as guest user in Azure AD V1.0 ,but you need to configure to point to the tenant-specific endpoint :https://login.microsoftonline.com/{TenantId_or_Name}). during authentication if you want to login with MSA in v1.0 apps.
Update:
You can use Code flow and azure ad v1.0 endpoint , user will be redirect to AAD's login page and enter their credential. Here is code sample for .net Core .
With Azure AD V1.0 endpoint , requests are sent to an endpoint that multiplexes across all Azure AD tenants: https://login.microsoftonline.com/common . When Azure AD receives a request on the /common endpoint, it signs the user in and, as a consequence, discovers which tenant the user is from. See document here . But in this scenerio ,you can only use work and school accounts(AAD) account to login .
The code sample in your link is using Azure Service Principal for Authentication , no interactive user login . You can use OpenID Connect Owin Middleware for authentication in .net Core applications as shown here .

Signing API requests on Azure App Services using MSI Access Token

I have a web application running on Azure App Services. The front-end (javascript + html + css) communicates with the backend (Flask). Both are runing on the same app service instance.
My app is protected by Active Directory Authentication (configured using Azure Portal).
User authentication to the app works perfectly. When a user navigates to the app, they are redirected to the login for our azure AD tenant. When they try to sign in, their permission to the app is controlled by their membership to an azure AD group. This bit works as expected
The challenge is that the front-end needs to send authenticated requests in order for them to actually reach the backend. They must be authenticated using a service principal token, not the user's token. And to this end, we are using the new, recommended approach; Managed Service Identity (MSI), not the service principal account workflow directly.
There are 2 stages to this:
1) Adding the authorization header
2) Ensuring that the MSI principal has access (i.e. belongs to the AD group)
1) The server generates an access token using the below code:
credentials = azure_active_directory.MSIAuthentication()
session = credentials.signed_session()
return session.headers.get("Authorization")
We then add the {"Authorization": "Bearer "} header where is the result of the above code.
This appears to work as expected - we are seeing long alphanumeric access tokens
2) The tricky bit was ensuring the MSI was added to the AD group. The GUIs at myapps.microsoft.com and mygroups.microsoft.com only allow the adding of users. Instead, I used the Azure CLI and ran the following:
a) Retrieve MSI principal ID
msiobjectid=$(az webapp identity show --resource-group <resource-group-name> --name <azure app services name> --query principalId)
b) Add principal to group
az ad group member add --group <group name> --member-id $msiobjectid
We are still getting 401 Unauthorized and we have exhausted all documentation :(
I should note that I only completed step 2 (adding the principal to the azure AD group via Azure CLI) about an hour ago. Perhaps there is a delay?
Edit: my scenario is closest to https://github.com/uglide/azure-content/blob/master/articles/app-service-api/app-service-api-dotnet-service-principal-auth.md except a) I'm using MSI, not a direct service principal and b) I have an extra layer of authorization, which is the ad groups, restricting access to the app to a few users rather than the whole tenant.
I believe you got this all backwards.
Your scenario is SPA + backend.
What you need to implement is OAuth 2.0 implicit grant flow as described here.
Source for diagram: dzimchuk.net
With the resulting access_token placed in the user-agent's session storage you can then call your backend. Use adal.js to make your life easier.
Since your Python backend IS a confidential client, you can now request an access token from the MSI endpoint for the desired audience (Azure resource), call it then filter the results so that it matches your access rights logic.
Note that at the time of writing only a subset of Azure resources are able to consume MSI-issued access tokens.

What is resource in Azure AD

I configured Azure AD as a IDP in a MFA scenario and gets an error as follows.
"invalid_request, ACS50001: The required field 'resource' is missing"
What should I give for the parameter resource?
Pass the application id that was created when you registered your application with AzureAD.
Resource parameter depicts the identifier of the WebAPI that your client wants to access on behalf of the user. Most flows in OAuth involve 4 parties, the resource owner (aka user), the client (aka app), the authority (aka identity provider) and the resource (aka webapi). The audience of the access token that the authority generates is the resource identifier.
In the case of Azure AD you can either use the Client ID or the App ID URI of the resource WebAPI (Find them in the configure tab of the Azure AD application in the Azure Management portal). For instance, if I want my client to get a token to access the Azure AD Graph API on behalf of the user, I would request for a token for resource "https://graph.windows.net".
Here are some code samples of Client Apps using Azure AD SDKs to request for tokens to WebAPIs - different usages of the resource parameter:
Mobile apps calling WebAPI: http://msdn.microsoft.com/en-us/library/azure/dn646737.aspx#BKMK_Native
Web apps calling WebAPI: http://msdn.microsoft.com/en-us/library/azure/dn646737.aspx#BKMK_AppToAPI
Clients calling Graph API: http://msdn.microsoft.com/en-us/library/azure/dn646737.aspx#BKMK_Graph
Hope this helps.

Resources