Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,83 @@ Entra ID is Microsoft's cloud-based identity and access management (IAM) platfor
- Cannot securely authenticate to the authorization server.
- **Security Implication:** An attacker can impersonate a public client application when requesting tokens, as there is no mechanism for the authorization server to verify the legitimacy of the application.

### ROPC / Password Grant

The OAuth2 **Resource Owner Password Credentials** (**ROPC**) flow uses a direct `POST` to `https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token` with `grant_type=password`, a **username**, **password**, a **client_id**, and the requested **scope**. In Entra ID this is mainly interesting for **public clients** because the attacker can reuse Microsoft first-party client IDs or any other allowed public client without needing a secret.

```bash
curl -X POST "https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=f05ff7c9-f75a-4acd-a3b5-f4b6a870245d" \
--data-urlencode "client_info=1" \
--data-urlencode "grant_type=password" \
--data-urlencode "username=user@corp.com" \
--data-urlencode "password=Password123!" \
--data-urlencode "scope=https://graph.microsoft.com/.default"
```

If the credentials are valid and the flow is allowed, Entra can return **access tokens** and sometimes **refresh tokens** that are immediately usable against Microsoft Graph or the target resource.

### Entra ID Sign-In Log Bypass Classes

Some historical Entra ID bugs allowed **password validation** or even **full token issuance** without generating the expected **Entra ID sign-in log** entry. These cases were fixed, but the techniques are still useful to understand how auth pipelines can fail in ways that leave **downstream token use visible** while the **upstream sign-in telemetry is absent**.

#### 1. Foreign-tenant endpoint for stealth password validation

If the request is sent to the token endpoint of a **different tenant GUID**, Entra may still validate whether the submitted password is correct for the supplied username before the flow fails because the user does not exist in that foreign tenant. Historically this allowed:

- **Password spraying / credential validation** without a corresponding sign-in log in the victim tenant
- A response difference that reveals whether the password step succeeded
- No token issuance, but less telemetry than a normal failed logon

#### 2. Force a post-password failure

If a parameter used **after** credential validation is invalid, such as an invalid `client_id`, the overall transaction may fail even though the password was already correct. Historically this produced a **failed** login view while hiding that the password guess succeeded.

The pattern to remember is:

- **Password check succeeds**
- A later validation step fails
- The log represents the final transaction state but not the successful password-validation step

#### 3. Trigger logging failure with oversized-but-valid values

The most dangerous class is when the request remains syntactically valid, authentication succeeds, **tokens are returned**, but some **logged field** is large enough to break the logging pipeline. Reported examples included:

- Repeating valid scopes thousands of times, such as `openid openid openid ...`
- Supplying an excessively long but still accepted **User-Agent** header

This suggests a general class of issues where:

1. Entra validates credentials and request syntax
2. The token is issued successfully
3. Logging attempts to persist a raw user-controlled field
4. The logging write fails because of length or schema assumptions
5. The user obtains a valid token with no corresponding sign-in record

Example of the repeated-scope pattern:

```bash
curl -X POST "https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=f05ff7c9-f75a-4acd-a3b5-f4b6a870245d" \
--data-urlencode "client_info=1" \
--data-urlencode "grant_type=password" \
--data-urlencode "username=user@corp.com" \
--data-urlencode "password=Password123!" \
--data-urlencode "scope=$(for num in {1..10000}; do echo -n 'openid '; done)"
```

#### Hunting / defensive note

Do not assume that every valid token use will have a matching Entra sign-in event. When investigating suspicious Graph activity, correlate:

- **Non-interactive sign-in logs**
- **Graph Activity Logs**
- **IP address**, **user/object ID**, **session/correlation identifiers**, and **time windows**

One practical validation method is to bracket a suspected invisible success between two normal failed logons and then verify whether the expected sequence `Failed -> Successful -> Failed` is missing the middle event after ingestion delay. If downstream Graph activity exists but the sign-in log does not, treat it as a potential **sign-in logging gap** or **token replay** condition.

## Authentication Tokens

There are **three types of tokens** used in OIDC:
Expand Down Expand Up @@ -566,5 +643,6 @@ From an attackers perspective it's very interesting to know where is it possible
- [https://github.com/Huachao/azure-content/blob/master/articles/active-directory/active-directory-token-and-claims.md](https://github.com/Huachao/azure-content/blob/master/articles/active-directory/active-directory-token-and-claims.md)
- [https://specterops.io/blog/2025/10/15/naa-or-broci-let-me-explain/](https://specterops.io/blog/2025/10/15/naa-or-broci-let-me-explain/)
- [https://specterops.io/blog/2025/08/13/going-for-brokering-offensive-walkthrough-for-nested-app-authentication/](https://specterops.io/blog/2025/08/13/going-for-brokering-offensive-walkthrough-for-nested-app-authentication/)
- [https://trustedsec.com/blog/full-disclosure-a-third-and-fourth-azure-sign-in-log-bypass-found](https://trustedsec.com/blog/full-disclosure-a-third-and-fourth-azure-sign-in-log-bypass-found)

{{#include ../../../banners/hacktricks-training.md}}