Auditing Insecure MFA Methods Used in Microsoft Entra With Log Analytics

As we all know, getting our organization onto Multi-factor authentication (MFA) is just the first step. The real challenge lies in moving to more secure second factors that can withstand increasingly sophisticated emerging threats. Unfortunately, industry support for moving to more advanced MFA methods is still not where it needs to be. But as security-minded individuals, we want to stay ahead of the curve and protect our users and environments from potential attacks.
One of the most significant vulnerabilities in MFA today is SMS-based attacks, including SIM swapping and SMS phishing (smishing). These tactics are becoming increasingly easy for threat actors to execute, and it’s essential that we eliminate insecure authentication methods where possible. To do so, we need to identify users who are still using them.
Identifying Insecure MFA Methods using KQL#
If you use Microsoft Azure Sentinel or a log analytics workspace, you can leverage KQL (Kusto Query Language) and the built-in Azure/Entra SignInLogs table to find out which users are still on “legacy” multifactor options. Here’s how:
KQL Query#
SigninLogs
| where TimeGenerated > ago(30d)
| extend AuthenticationMethod = tostring(parse_json(AuthenticationDetails)[0].authenticationMethod)
| extend AuthenticationMethodDetail = tostring(parse_json(AuthenticationDetails)[0].authenticationMethodDetail)
| extend MfaMethod = tostring(parse_json(AuthenticationDetails)[1].authenticationMethod)
| where parse_json(AuthenticationDetails)[0].succeeded == true and parse_json(AuthenticationDetails)[1].succeeded == true
| where AuthenticationMethod != "Previously satisfied"
| where MfaMethod != "Previously satisfied"
| where MfaMethod != "Mobile app notification"
| distinct UserPrincipalName, AuthenticationMethod, AuthenticationMethodDetail, MfaMethod
This query will help you identify users who are still using insecure MFA methods, such as SMS-based authentication (text messages, voice calls) and OATH verification codes. You can adjust the timeframe by modifying the TimeGenerated
value in the query.
This query is quite complex, so let’s break it down step by step:
Step 1: Filter the data to only include logs from the last 30 days
SigninLogs | where TimeGenerated > ago(30d)
This line filters the SigninLogs
table to only include records with a timestamp greater than 30 days ago. This ensures that we’re only looking at recent activity.
Step 2: Extract and parse the authentication details from the log data
| extend AuthenticationMethod = tostring(parse_json(AuthenticationDetails)[0].authenticationMethod)
| extend AuthenticationMethodDetail = tostring(parse_json(AuthenticationDetails)[0].authenticationMethodDetail)
| extend MfaMethod = tostring(parse_json(AuthenticationDetails)[1].authenticationMethod)
Here, we’re using the extend
function to create new fields based on the data in the AuthenticationDetails
column. This column contains a JSON object with various attributes related to the sign-in event.
- The first line extracts the
authenticationMethod
value from the first element of theAuthenticationDetails
array. - The second line attempts to extract any available information from the
authenticationMethodDetail
array. - The third line extracts the
mfaMethod
value from the second element of theAuthenticationDetails
array.
Step 3: Filter the data to only include successful sign-in events
| where parse_json(AuthenticationDetails)[0].succeeded == true and parse_json(AuthenticationDetails)[1].succeeded == true
This line filters the data to only include records where both authentication methods were successfully used.
Step 4: Filter out “Previously satisfied” authentication method
| where AuthenticationMethod != "Previously satisfied"
Here, we’re filtering out records with an AuthenticationMethod
value of "Previously satisfied"
.
Step 5: Filter out “Mobile app notification” MFA method
| where MfaMethod != "Mobile app notification"
This line filters out records with an MfaMethod
value of "Mobile app notification"
.
Step 6: Show the deduplicated results
| distinct UserPrincipalName, AuthenticationMethod, AuthenticationMethodDetail, MfaMethod
Finally, we’re grouping the results by the specified columns to eliminate duplicates.
Next Steps: Creating a Phishing Resistant Conditional Access Policy
Now that you’ve identified users who are still using insecure MFA methods, it’s time to take action and move them to better methods. To further harden the environment against authentication-based attacks, I recommend creating a phishing resistant conditional access policy.
The official guidance for creating such a policy can be found on Microsoft’s Entra documentation: <https://learn.microsoft.com/en-us/entra/identity/conditional-access/how-to-policy-phish-resistant-admin-mfa>. This policy will ensure that even administrative accounts are protected from phishing attacks, using advanced MFA methods like FIDO2 security keys or authenticator apps.
By implementing this policy, you’ll be taking a significant step towards securing your organization’s MFA and protecting it against the most sophisticated threats.
Sources: Microsoft Learn - Conditional Access authentication strength Microsoft Learn - Common Conditional Access policy: Require phishing-resistant multifactor authentication for administrators Nathan McNulty - Twitter