Skip Navigation
Get a Demo
 
 
 
 
 
 
 
 
 
Resources Blog Microsoft

Investigating legacy authentication: The curious case of "BAV2ROPC"

A mysterious user agent string in some Microsoft 365 audit logs offers clues for how to detect logon sessions from legacy authentication protocols.

Justin Schoenfeld
Originally published . Last modified .

“BAV2ROPC” is an undocumented protection mechanism that Microsoft developed to aid in thwarting legacy authentication attacks. In this blog, we explain the feature, explore the problem it solves, and offer practical advice for testing it.

Microsoft has been slowly but surely deprecating basic authentication against legacy exchange services like POP, Exchange Active Sync (EAS), Remote PowerShell, and others. SMTP AUTH will remain supported because devices that don’t support modern authentication—like scanners and printers—continue to rely on it, although Microsoft strongly suggests that organizations stop using it if possible.

The problem with basic authentication

Note: For brevity sake, the rest of this post will synonymously mention basic and legacy authentication. In fact, these terms are interchangeable, according to Microsoft’s definition from a great talk they gave at RSA 2020:

“Legacy or Basic authentication refers to older protocols like POP, SMTP, XML-Auth, which don’t allow for rich user interaction, multi-factor authentication challenges, or device verification”

It’s important to note that the conversion process we’ll talk about may not result in a full transition to modern authentication, as certain modern authentication features such as MFA may not be fully supported. Therefore, in this context, the term ‘modern authentication’ should be interpreted with this limitation in mind.

Summarizing Microsoft’s own description of the problem, basic authentication is an outdated industry standard that allows applications to send usernames and passwords with every authentication request, making it easier for attackers to capture and abuse user credentials. Additionally, it’s sometimes difficult or impossible to enforce multi-factor authentication (MFA) for systems using basic authentication. The deprecation of basic authentication represents a giant step towards protecting credentials and widening the adoption of MFA.

In fact, this is not an abstract problem. Adversaries have very commonly abused legacy authentication as an initial attack vector against Microsoft services. Microsoft has previously shared some shocking statistics related to legacy authentication and how important it is for these protocols to be disabled in your environment:

  • More than 99 percent of password spray attacks use legacy authentication protocols.
  • More than 97 percent of credential stuffing attacks use legacy authentication.
  • Azure AD accounts in organizations that have disabled legacy authentication experience 67 percent fewer compromises than those where legacy authentication is enabled.

Microsoft presented the following graphic at RSA Conference in 2020, showing that SMTP was the top victim protocol for password-based attacks at that time. Unfortunately, this problem will likely persist for as long as basic authentication for SMTP AUTH remains supported.

Microsoft presented this graphic at RSA Conference in 2020.

Improvements in modern authentication

Modern authentication standards like OAuth 2.0 prevent applications from handling usernames and passwords and instead route the user authentication process through an Identity Provider (IdP) such as Azure Active Directory. It operates on a standardized authorization framework that prompts users to validate their identity within the IdP while also enforcing additional protective mechanisms like multi-factor. OAuth 2.0 uses the term “client” to refer to an application that requires authorization on behalf of a “resource owner” or user. For example, logging in through https://login.microsoftonline.com/ is a common way to authenticate users with Azure Active Directory.

Upon successfully validating a credential, the IdP grants access via a token. While OAuth 2.0 includes a flow called Resource Owner Password Credential (ROPC) that allows a client to accept and transmit valid credentials and pass them on to the IdP for token grants, its use is highly discouraged because it’s similar to the way that basic authentication works and suffers many of same security shortcomings. Ideally, organizations and application developers ought to support the more secure OAuth 2.0 flows instead such as the Authorization Grant, which we’ll discuss later on.

Many legacy devices and applications that rely on basic email functionality—such as printers, scanners, and older applications—still use SMTP AUTH for sending mail. As a result, Microsoft has chosen not to block this authentication method by default at this time. In light of this, we decided to investigate relevant attack scenarios that target legacy authentication technologies and review the telemetry they generate, so defenders have a full understanding of what to look for and how to prevent such attacks.

However, during our testing, we noticed a seemingly undocumented, but briefly mentioned mechanism in place where Microsoft translates a legacy authentication session to a somewhat modern authentication session via the previously mentioned ROPC flow. When this conversion occurs, an unusual string gets populated in the user agent section of the logs we monitor. This string has baffled many people in the security community. As a result, we decided to investigate the matter further, provide some clarity, and share our findings.

Onto the mystery: BAV2ROPC

While conducting regular analysis of our customers’ Microsoft 365 audit logs, we noticed the user agent BAV2ROPC kept appearing. This piqued our interest not only because we were unsure of its meaning, but also because we observed widespread confusion among system administrators, security analysts, developers, and other professionals in the security industry about its meaning.

After conducting a Google search for the user agent string BAV2ROPC, we found a range of speculations on social media, technical forums, and blogs. Some suggest that it’s statically assigned in a popular open source password brute-forcing tool called Hydra, while others believe it represents outdated Outlook Mobile clients or is directly linked to a botnet campaign. One forensics-related article suggested that the user agent is associated with mailbox syncing via legacy authentication.

The string is actually an acronym for “Basic Authentication Version 2 Resource Owner Password Credential.” Microsoft doesn’t explicitly detail where or how this string is set but has briefly mentioned it in a few of their blogs and documentation.

The following table includes some statistics associated with this user agent in customer environments over the past month:

Authentication typeSuccessesFailures
Authentication type:

Legacy authentication

Successes :

11,456

Failures :

7,077,770

Authentication type:

Modern authentication (OAuth 2.0)

Successes :

85,799,705

Failures :

12,470,931

This means legacy authentication has a success rate of 0.16 percent, while the success rate for modern authentication is 87.32 percent. Despite Microsoft’s actions to disable legacy authentication, we observe that adversaries are still frequently launching password-based attacks against it.

A seamless, “semi-modern” authentication experience

We have confirmed through testing that this user agent is set by Microsoft when it identifies basic/legacy authentication from legacy protocols like SMTP AUTH. It’s not a user agent statically defined by brute force tools, nor is it directly linked to specific botnet campaigns as previously speculated. BAV2ROPC is a seemingly undocumented mechanism developed by Microsoft that allows old applications that continue to rely on legacy authentication to switch in real-time to OAuth 2.0 using the ROPC flow. This means they provided a way for legacy applications to upgrade to “modern authentication” on the fly without requiring developers to upgrade the application itself to support more secure OAuth 2.0 flows like the Authorization Grant.

Historically, adversaries would abuse legacy authentication to bypass MFA by leveraging authentication protocols that don’t support it. Whether or not an account had MFA enabled, logging in via SMTP AUTH, for example, would skip MFA altogether. With BAV2ROPC, you can (sort of) enforce MFA in that authentication can be blocked for protocols that don’t support MFA when MFA is enabled on a user principal. The OAuth 2.0 Authorization Framework request for comment (RFC) itself even describes the ROPC flow as a great way to convert older applications from basic to modern OAuth-based authentication:

“This grant type is suitable for clients capable of obtaining the resource owner’s credentials (username and password, typically using an interactive form). It is also used to migrate existing clients using direct authentication schemes such as HTTP Basic or Digest authentication to OAuth by converting the stored credentials to an access token.”

This is achieved by intercepting legacy authentication requests and exchanging the credentials for an OAuth 2.0 access token, which is stored within the client. A typical client that supports the ROPC flow simply accepts a username and password from a resource owner, then sends it to an IdP in exchange for an access token. After successfully gaining the proper tokens, the application is supposed to securely discard the credentials altogether, as they’re no longer needed.

Here is a brief graphical overview of the ROPC flow from Microsoft’s documentation:

ROPC flow

Since Microsoft’s BAV2ROPC mechanism translates authentication to ROPC, and the ROPC standard doesn’t allow the user to interact with the IdP directly, there’s essentially no way for them to fully accomplish any type of MFA like number matching or SMS one-time passcodes (OTP). The limitations of ROPC are well documented.

Compared to the most popular flow used by applications, the Authorization Code Flow, the user directly enters their own credentials within the IdP’s authorization server, allowing for the tenant’s authentication policies to take effect. Microsoft has provided a graphical example of what this process looks like:

Authorization Code Flow in Microsoft Identity platform

With this flow, the user interacts with the IdP during that “browser dialog” portion, which is essentially presenting the user with the authorization server’s login screen and any subsequent MFA prompts to validate their identity against the tenant’s authentication policies.

Diving into the logs

Since SMTP communication is not used for retrieving web-based content, we would have expected the BAV2ROPC user agent to be null. Given that Microsoft is transparently performing this basic-to-modern authentication mechanism, they essentially provided a unique string for us to determine when this conversion occurs. Unfortunately, you can’t filter the logs on specific user agents within the Azure portal. Luckily, there are a bunch of other ways to find users that are still relying on legacy applications.

Sign-in logs: Authentication protocol

We can create a filter on the sign-in logs in our Azure Active Directory blade for the “ROPC” authentication protocol:

Sign-in logs for ROPC authentication protocol in Azure Active Directory

Sign-in logs: Client app filter

Another way to filter is to use the same sign-in logs page and add the filter for “Client Apps.” This will also display a list of legacy authentication clients used in your environment:

Sign-in logs for client applications in Azure Active Directory

Azure AD Log Analytics Workbook

Yet another way to filter is through an Azure AD workbook. You can access this via Log Analytics, which requires a premium P1 or P2 license. To find this workbook, navigate to your Azure AD instance, under Monitoring > Workbooks. Find the Workbook under Usage named “Sign-ins using Legacy Authentication,” which has a helpful description of what the underlying KQL query identifies:

“This workbook highlights which legacy authentication protocols are used throughout your tenant. Legacy authentication (or basic authentication) protocols do not support multi-factor authentication. Microsoft highly recommends blocking legacy authentication and will be deprecating the use of legacy protocols for Exchange Online.”

SigninLogs
| project
    TimeGenerated,
    UserPrincipalName,
    ClientAppUsed,
    Status,
    AppDisplayName,
    HomeTenantId,
    ResourceTenantId
| where TimeGenerated > ago(1d)
| where "All users" == "All users" or UserPrincipalName has "All users"
| where "All applications" == "All applications" or AppDisplayName has "All applications"
| extend status = case(Status.errorCode == 0, "Success", "Failure")
| where "Success" == status or "Success" == "All"
| where ClientAppUsed != "Browser" and ClientAppUsed != "Mobile Apps and Desktop clients"
| where HomeTenantId == ResourceTenantId
| extend Protocol = case(ClientAppUsed != "", ClientAppUsed, "Unknown")
| summarize Users = dcount(UserPrincipalName) by AppDisplayName, Protocol
| sort by Users desc

Disabling or enabling SMTP AUTH

There are a few different settings for enabling or disabling SMTP AUTH in the Exchange Admin Center, as well as the Microsoft 365 Admin Center. During our testing, we noticed that even when some settings to disable basic authentication were enabled globally, other settings effectively overrode them. In essence, you may see that global SMTP AUTH is disabled on one page, but it’s possible many individual users may have it enabled—leaving a false sense of protection.

Exchange Admin Center: SMTP AUTH

To disable SMTP AUTH, log into the Exchange Admin Center, then navigate to the Settings section. Click on Mail Flow, and make sure “Turn off SMTP AUTH protocol for your organization” is checked to ensure it’s disabled.

You can also check and change this setting with PowerShell:

# Change the setting
Set-TransportConfig -SmtpClientAuthenticationDisabled $true

# Verify setting changed
Get-TransportConfig | Format-List SmtpClientAuthenticationDisabled

Microsoft 365 Admin Center: Basic authentication protocols

There’s a setting in the Microsoft Admin Center that turns off certain basic authentication protocols. Within the UI, this setting can be found under Settings > Org Settings > Modern Authentication. From this page you’ll be able to select which basic authentication protocols your organization requires. If we’re looking to generate successful login telemetry, we’ll check the Authenticated SMTP protocol. This can also be done via PowerShell:

# Change the setting
Set-OrganizationConfig -OAuth2ClientProfileEnabled $true

# Verify setting changed
Get-OrganizationConfig | Format-Table Name,Oauth2*

Additionally you can disable basic authentication via authentication policies per individual users. For more information, this helpful article in Microsoft’s documentation details the process in its entirety. The high-level steps are to create a new authentication policy, disable basic authentication protocols in the policy, and then assign it to a user:

# Create new policy 
New-AuthenticationPolicy -Name "Block Basic Auth"

# Modify policy to disable authenticated smtp
Set-AuthenticationPolicy -Identity "Block Basic Auth" -AllowBasicAuthSmtp:$false

# Assign the policy to user
Set-User -Identity user@your_tenant.com -AuthenticationPolicy "Block Basic Auth"
# View Authentication Policy 
Get-AuthenticationPolicy -Identity "Block Basic Auth"

Microsoft 365 Admin Center: Manage email apps per user

Another setting that we’ve identified that can override the global settings we previously mentioned exists in each user’s mail settings. When you enable “Authenticated SMTP” in this manner, it will negate the other two settings. This setting exists under Users > Select a user > Mail > Manage Email Apps. This screen will also allow you to control which protocols an individual is permitted to use. This can also be done via PowerShell:

# Disable basic auth for a specific mailbox 
Set-CASMailbox -Identity user@your_tenant.com -SmtpClientAuthenticationDisabled $true

# Verify Setting Change 
Get-CASMailbox -Identity user@your_tenant.com  | Format-List SmtpClientAuthenticationDisabled

Generate and retrieve telemetry

Python

To generate a BAV2ROPC SMTP AUTH authentication event in the Unified Audit Log (UAL) or Sign-in logs, you can leverage the smtplib Python library. You can optionally enable debug logging to see the raw requests and responses as well. In a Python shell, we’ll execute the following commands:

import smtplib
s = smtplib.SMTP(host='smtp-mail.outlook.com', port=587)
s.debuglevel=2
s.starttls()
s.login(test@some_tenant.onmicrosoft.com', 'YOURPASSWORD')

PowerShell

Alternatively, the following PowerShell cmdlet sends messages over SMTP, which will also generate some BAV2ROPC telemetry.

# Setup credentials
$Creds = Get-Credential -Credential test@your_tenant.onmicrosoft.com'

# Login and send a test email
Send-MailMessage -From 'sender@your_tenant.com' -To 'user_xyz@gmail.com' -Subject 'Test!' -SmtpServer 'smtp.office365.com' -Credential $Cred -UseSsl

Log samples

After executing one or more of our SMTP AUTH basic authentication tests above, we can find the BAV2ROPC user agent as we discussed earlier. Additionally, we can grab these UAL logs in a few different ways. The easiest way is to go to the Compliance Center and run an audit search for logs of Category AzureActiveDirectoryStsLogon, which corresponds to a Record Type of 15.

Note that when you’re exporting this data via the Compliance Center, the format of the logs is not as desirable as querying directly via the Office 365 Management API. When dumped via the Compliance Center UI, most of the interesting data fields are dumped into an AuditData field, which requires deeper parsing. An even easier route for log collection is to utilize one of many open source tools to collect this data for you, such as the Microsoft 365 Extractor Suite by Invictus or Sparrow, created by the Cybersecurity and Infrastructure Security Agency (CISA).

Unified Audit Log

After running our tests above, an example of our BAV2ROPC event retrieved directly from the O365 management API can be seen below:

{
  "CreationTime": "2023-01-01T01:01:01",
  "Id": "3d7dcbb5-baf8-414b-ae23-aa5de75abe01",
  "Operation": "UserLoggedIn",
  "OrganizationId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "RecordType": 15,
  "ResultStatus": "Success",
  "UserKey": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "UserType": 0,
  "Version": 1,
  "Workload": "AzureActiveDirectory",
  "ClientIP": "3.4.5.6",
  "ObjectId": "00000002-0000-0ff1-ce00-000000000000",
  "UserId": "test@some_tenant.onmicrosoft.com",
  "AzureActiveDirectoryEventType": 1,
  "ExtendedProperties": [
    {
      "Name": "ResultStatusDetail",
      "Value": "Success"
    },
    {
      "Name": "UserAgent",
      "Value": "BAV2ROPC"
    },
    {
      "Name": "UserAuthenticationMethod",
      "Value": "1"
    },
    {
      "Name": "RequestType",
      "Value": "OAuth2:Token"
    }
  ],
  "ModifiedProperties": [],
  "Actor": [
    {
      "ID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
      "Type": 0
    },
    {
      "ID": "test@some_tenant.onmicrosoft.com",
      "Type": 5
    }
  ],
  "ActorContextId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "ActorIpAddress": "3.4.5.6",
  "InterSystemsId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "IntraSystemId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "SupportTicketId": "",
  "Target": [
    {
      "ID": "00000002-0000-0ff1-ce00-000000000000",
      "Type": 0
    }
  ],
  "TargetContextId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "ApplicationId": "00000002-0000-0ff1-ce00-000000000000",
  "DeviceProperties": [
    {
      "Name": "BrowserType",
      "Value": "Other"
    },
    {
      "Name": "IsCompliantAndManaged",
      "Value": "False"
    },
    {
      "Name": "SessionId",
      "Value": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    }
  ],
  "ErrorNumber": "0"
}

Sign-in log

The UAL data is an excerpt from the Azure AD Sign-in log, which unfortunately leaves a bit to be desired, as shown below in the original log that also displays items like token scopes, user geo-location, and authentication protocol. The full content of the Sign-in log is shown below:

{
    "id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "createdDateTime": "2023-01-01T01:01:01",
    "userDisplayName": "Test Accounts",
    "userPrincipalName": "test@some_tenant.onmicrosoft.com",
    "userId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "appId": "00000002-0000-0ff1-ce00-000000000000",
    "appDisplayName": "Office 365 Exchange Online",
    "ipAddress": "3.4.5.6",
    "ipAddressFromResourceProvider": null,
    "clientAppUsed": "Authenticated SMTP",
    "userAgent": "BAV2ROPC",
    "correlationId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "conditionalAccessStatus": "notApplied",
    "originalRequestId": "",
    "isInteractive": true,
    "tokenIssuerName": "",
    "tokenIssuerType": "AzureAD",
    "clientCredentialType": "clientAssertion",
    "processingTimeInMilliseconds": 136,
    "riskDetail": "none",
    "riskLevelAggregated": "none",
    "riskLevelDuringSignIn": "none",
    "riskState": "none",
    "riskEventTypes_v2": [],
    "resourceDisplayName": "Office 365 Exchange Online",
    "resourceId": "00000002-0000-0ff1-ce00-000000000000",
    "resourceTenantId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "homeTenantId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "homeTenantName": "",
    "authenticationMethodsUsed": [],
    "authenticationRequirement": "singleFactorAuthentication",
    "signInIdentifier": "test@some_tenant.onmicrosoft.com",
    "signInIdentifierType": null,
    "servicePrincipalName": null,
    "signInEventTypes": [
      "interactiveUser"
    ],
    "servicePrincipalId": "",
    "federatedCredentialId": null,
    "userType": "member",
    "flaggedForReview": false,
    "isTenantRestricted": false,
    "autonomousSystemNumber": 7922,
    "crossTenantAccessType": "none",
    "servicePrincipalCredentialKeyId": null,
    "servicePrincipalCredentialThumbprint": "",
    "uniqueTokenIdentifier": "tctfi6S0GuI6pd51q-AQ",
    "incomingTokenType": "none",
    "authenticationProtocol": "ropc",
    "resourceServicePrincipalId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "mfaDetail": null,
    "authenticationAppDeviceDetails": null,
    "status": {
      "errorCode": 0,
      "failureReason": "Other.",
      "additionalDetails": null
    },
    "deviceDetail": {
      "deviceId": "",
      "displayName": "",
      "operatingSystem": "",
      "browser": "",
      "isCompliant": false,
      "isManaged": false,
      "trustType": ""
    },
    "location": {
      "city": "XXXXXX",
      "state": "XX",
      "countryOrRegion": "US",
      "geoCoordinates": {
        "altitude": null,
        "latitude": 11.11111,
        "longitude": -11.1111
      }
    },
    "appliedConditionalAccessPolicies": [],
    "authenticationContextClassReferences": [],
    "authenticationProcessingDetails": [
      {
        "key": "Root Key Type",
        "value": "Unknown"
      },
      {
        "key": "Oauth Scope Info",
        "value": "[\"AuditLog.Create\",\"Channel.ReadBasic.All\",\"Chat.Read\",\"DataLossPreventionPolicy.Evaluate\",\"Directory.Read.All\",\"EduRoster.ReadBasic\",\"Files.ReadWrite.All\",\"Group.ReadWrite.All\",\"InformationProtectionPolicy.Read\",\"Notes.Create\",\"OnlineMeetings.Read\",\"OnlineMeetings.ReadWrite\",\"People.Read\",\"SensitiveInfoType.Detect\",\"SensitiveInfoType.Read.All\",\"SensitivityLabel.Evaluate\",\"User.Invite.All\",\"User.Read\",\"User.ReadBasic.All\"]"
      }
    ],
    "networkLocationDetails": [],
    "authenticationDetails": [
      {
        "authenticationStepDateTime": "2023-01-11T11:11:11",
        "authenticationMethod": "Password",
        "authenticationMethodDetail": "Password in the cloud",
        "succeeded": true,
        "authenticationStepResultDetail": "Correct password",
        "authenticationStepRequirement": ""
      }
    ],
    "authenticationRequirementPolicies": [],
    "sessionLifetimePolicies": [],
    "privateLinkDetails": {
      "policyId": "",
      "policyName": "",
      "resourceId": "",
      "policyTenantId": ""
    },
    "appliedEventListeners": [],
    "authenticationAppPolicyEvaluationDetails": []
  }

There are some interesting observations to make from this log file. Firstly, we’re using basic authentication, yet, the log file populated some OAuth scopes under the authenticationProcessingDetails section. We can also see that the authenticationProtocol is ROPC, and the clientAppUsed used is Authenticated SMTP. This further proves that we’re automatically transitioned from basic to modern authentication.

Got the creds. Now what?

Let’s say an adversary discovered valid credentials and logged in via SMTP successfully since MFA on the victim’s account was disabled. With their newly gained access, they can attempt to send mail on behalf of this user via SMTP. Adversaries could use this access to potentially to further phish users or send mass spam mail to targets of their choosing. Since we’re not accessing the account via IMAP or POP (due to those protocols being disabled), they wouldn’t have access to the user’s mailbox.

We could simply use the PowerShell command above to mimic this activity, but as an alternative example, this Python script will also do the trick:

from email.mime.text import MIMEText
import smtplib
from email.header import Header

USERNAME = 'test@some_tenant.onmicrosoft.com'
PASSWORD = 'xxxxx'
msg = MIMEText('Your payload', 'plain', 'utf-8')
msg['From'] = 'test@some_tenant.onmicrosoft.com'
msg['To'] = 'user@gmail.com'
msg['Subject'] = Header('Test email', 'utf-8')
msg.set_payload('Base64 your payload or html')

s = smtplib.SMTP(host='smtp-mail.outlook.com', port=587)
s.starttls()
s.login(USERNAME, PASSWORD)

s.send_message(msg)

Normally, when users send mail via applications like OWA and a tenant has premium audit logging enabled in Microsoft Purview, we’ll see Send Operations. During testing, we noticed that when sending mail via a legacy authentication method such as the Python script above, we didn’t see the BAV2ROPC user agent. Instead, we noticed the following ClientInfoString in the Send Operations:

Client=Hub Transport;User=test@some_tenant.onmicrosoft.com;IsClientSubmission=True

Running a search against your Send Operations for this pattern may indicate what accounts are sending mail directly via SMTP. Interestingly, the audit logs do not display the IP address of the sender; the IP always displays as an IPv6 loopback address of ::1.

Alternatively, since adversaries have identified valid credentials, they can also simply login to public applications that support the ROPC flow. For details on this technique, read our deeper dive into ROPC.

Additionally, since we have valid credentials on an account without MFA, we can simply input those credentials into a ROPC flow against any public client application that supports ROPC. For example, to generate this login flow locally, we can simply use the following cURL command with their credentials and grab an access token for that application. In this case, we’re using the client Microsoft Outlook, otherwise referred to by its client_id or application ID of 5d661950-3475-41cd-a2c3-d671a3162bc1. Note we’re using the organization’s token endpoint URL. Alternatively, you could use the victim’s tenant ID, if available.

curl --request POST \
  --url 'https://login.microsoftonline.com/organizations/oauth2/v2.0/token' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data grant_type=password \
  --data client_id=5d661950-3475-41cd-a2c3-d671a3162bc1 \
  --data username=VICTIM_PRINCIPAL_NAME \
  --data password=''PASSWORD” \
  --data scope=https://graph.microsoft.com/.default <- OPTIONAL

In this case, the client ID 5d661950-3475-41cd-a2c3-d671a3162bc1 corresponds to Microsoft Outlook. With our newly obtained token with the following default scopes, we can read/send mail on behalf of the user as well as perform actions against the other permissions granted:

  • email
  • openid
  • profile
  • https://graph.microsoft.com/AuditLog.Create
  • https://graph.microsoft.com/Channel.ReadBasic.All
  • https://graph.microsoft.com/Chat.Read
  • https://graph.microsoft.com/DataLossPreventionPolicy.Evaluate
  • https://graph.microsoft.com/Directory.Read.All
  • https://graph.microsoft.com/EduRoster.ReadBasic
  • https://graph.microsoft.com/Files.ReadWrite.All
  • https://graph.microsoft.com/Group.ReadWrite.All
  • https://graph.microsoft.com/InformationProtectionPolicy.Read
  • https://graph.microsoft.com/OnlineMeetings.Read
  • https://graph.microsoft.com/People.Read
  • https://graph.microsoft.com/SensitiveInfoType.Detect
  • https://graph.microsoft.com/SensitiveInfoType.Read.All
  • https://graph.microsoft.com/SensitivityLabel.Evaluate
  • https://graph.microsoft.com/User.Invite.All
  • https://graph.microsoft.com/User.Read
  • https://graph.microsoft.com/User.ReadBasic.All
  • https://graph.microsoft.com/User.ReadWrite
  • https://graph.microsoft.com/.default

Takeaways

It’s widely suggested that, where possible, enterprises turn on Security Defaults within their tenants. According to Microsoft, enabling this setting in your Azure Active Directory can prevent 99.9 percent of identity-based attacks. The most impactful changes of this setting include requiring administrators and users to register for MFA and automatic disabling of legacy authentication protocols. If for some reason you cannot enable security defaults, verifying your legacy authentication posture and disabling SMTP with the methods we provided should help fill the gaps.

Further reading on disabling basic authentication

More resources

 

Teaming with Microsoft Copilot for Security

 

Red Canary brings MDR expertise to Microsoft Azure Cloud

 

How Red Canary supports Microsoft customers

 

When MFA isn’t an option: The legacy of ROPC

Subscribe to our blog

 
 
Back to Top