SSPR/MFA

What Is SSPR

Attack

If you have control of an MFA method that is available to a user, you can reset their password without knowing their password.

Detect

Hunt for known bad MFA devices

Below scripts lists all MFA methods by every user and lists their properties.

param ($Path, $UserList)

if ( ($Path -eq $null) -or ($Path -eq "") -or ($Path -eq " "))
{
	Write-Host "-Path not valid, please provide a filepath to export CSV to."
	Write-Host "-UserList, to optionally add a list of users to save time. By default grabs a list of every user in the tenant."
}
else 
{
	#Connect MgGraph
	Connect-MgGraph -Scopes 'UserAuthenticationMethod.Read.All' -NoWelcome

	if ($UserList -eq $null)
	{
		# Display the custom objects
		#Get all Azure users
		$users = get-mguser -All
	}
	else
	{
		#Provide list of users
		$users = ForEach ($mguser in $(get-content -Path $UserList)) {
		get-mguser -userid $mguser
		}
	}
	$results=@();
	Write-Host  "`nRetreived $($users.Count) users";
	#loop through each user account
	foreach ($user in $users) {

	$MFAData=Get-MgUserAuthenticationMethod -UserId $user.UserPrincipalName #-ErrorAction SilentlyContinue

		#check authentication methods for each user
		ForEach ($method in $MFAData) {
			$myObject = [PSCustomObject]@{
				user               		= "-"
				Id 				   		= "-"
				MFAstatus          		= "-"
				email              		= "-"
				fido2              		= "-"
				app                		= "-"
				password           		= "-"
				phone              		= "-"
				softwareoath       		= "-"
				tempaccess         		= "-"
				hellobusiness      		= "-"
				DeviceName         		= "-"
				PhoneAppVersion    		= "-"
				DeviceTag		  		= "-"
			}

			$myobject.user = $user.UserPrincipalName;
			Switch ($method.AdditionalProperties["@odata.type"]) {
				"#microsoft.graph.emailAuthenticationMethod"  { 
				$myObject.Id = $method.Id
				$myObject.email = $true 
				$myObject.MFAstatus = "Enabled"
			} 
				"#microsoft.graph.fido2AuthenticationMethod" { 
				$myObject.fido2 = $true 
				$myObject.MFAstatus = "Enabled"
			}    
				"#microsoft.graph.passwordAuthenticationMethod"                {              
				$myObject.password = $true 
					# When only the password is set, then MFA is disabled.
					if($myObject.MFAstatus -ne "Enabled")
					{
						$myObject.MFAstatus = "Disabled"
					}                
			}     
				"#microsoft.graph.phoneAuthenticationMethod"  { 
				$myObject.phone = $true
				$myObject.MFAstatus = "Enabled"
			}
			"#microsoft.graph.microsoftAuthenticatorAuthenticationMethod"  {
				$myObject.Id = $method.Id 
				$myObject.DeviceName = $method.AdditionalProperties.displayName
				$myObject.PhoneAppVersion = $method.AdditionalProperties.phoneAppVersion
				$myObject.deviceTag = $method.AdditionalProperties.deviceTag
				$myObject.MFAstatus = "Enabled"
			}
		
				"#microsoft.graph.softwareOathAuthenticationMethod"  {
				$myObject.Id = $method.Id 
				$myObject.softwareoath = "Oath OTP Enabled" 
				$myObject.MFAstatus = "Enabled"
			}           
				"#microsoft.graph.temporaryAccessPassAuthenticationMethod"  { 
				$myObject.tempaccess = $true 
				$myObject.MFAstatus = "Enabled"
			}           
				"#microsoft.graph.windowsHelloForBusinessAuthenticationMethod"  { 
				$myObject.hellobusiness = $true 
				$myObject.MFAstatus = "Enabled"
			}                   
			}
		$results+= $myObject;
		}
	}
	# Display the custom objects
	$results | export-csv -path $Path
}

What logs are available?

Audit Logs:

Password is not required for SSPR, only an alternate authentication method.

SSPR activity flow:

  1. User submitted their user ID

  2. User was presented with verification options

  3. User started the mobile app code verification option

  4. User completed the mobile app code verification option

  5. User completed all verification steps required to reset their password

  6. User submitted a new password

  7. Reset user password

  8. Update StsRefreshTokenValidFrom Timestamp

  9. Successfully completed reset.

First MFA:

OLD VALUE:

{"DeviceName":"SM-S911U","DeviceToken":"fdP4zadhT9mVkYYo_yQqEz:APA91bF61gVUucY6QWx2eWDi5IaSxCbSAM6LWsNGMmiiNXLgzCughKpLH5Nm2BetAEkl0axD2_ySPOJ24TEc0Wh-wwDeQBH-VP5c7rEme-xPTPioBPs-KsO5ftitRu4YG218wxXmII1Z",
"DeviceTag":"SoftwareTokenActivated",
"PhoneAppVersion":"6.2309.6329",
"OathTokenTimeDrift":0,
"DeviceId":"00000000-0000-0000-0000-000000000000",
"Id":"8cb20903-8109-4518-8269-a82dab749591","TimeInterval":0,
"AuthenticationType":3,
"NotificationType":4,
"LastAuthenticatedTimestamp":"2023-10-25T06:38:08.344692Z",
"AuthenticatorFlavor":null,
"HashFunction":null,
"TenantDeviceId":null,
"SecuredPartitionId":0,
"SecuredKeyId":0}


NEW VALUE:

{"DeviceName":"SM-S911U",
"DeviceToken":"fdP4zadhT9mVkYYo_yQqEz:APA91bF61gVUucY6QWx2eWDi5IaSxCbSAM6LWsNGMmiiNXLgzCughKpLH5Nm2BetAEkl0axD2_ySPOJ24TEc0Wh-wwDeQBH-VP5c7rEme-xPTPioBPs-KsO5ftitRu4YG218wxXmII1Z",
"DeviceTag":"SoftwareTokenActivated",
"PhoneAppVersion":"6.2309.6329",
"OathTokenTimeDrift":0,
"DeviceId":"00000000-0000-0000-0000-000000000000",
"Id":"8cb20903-8109-4518-8269-a82dab749591",
"TimeInterval":0,
"AuthenticationType":3,
"NotificationType":4,
"LastAuthenticatedTimestamp":"2024-12-12T12:38:08.344692Z",
"AuthenticatorFlavor":"Authenticator",
"HashFunction":"hmacsha256",
"TenantDeviceId":null,
"SecuredPartitionId":0,"SecuredKeyId":0}]

AuthenticationFlavor is updated from null, to authenticator (not sure why):

  • "AuthenticatorFlavor":null,

  • "AuthenticatorFlavor":"Authenticator",

LastAuthenticatedTimestamp is sometimes updated (note sure when):

  • "LastAuthenticatedTimestamp":"2023-10-25T06:38:08.344692Z",

  • "LastAuthenticatedTimestamp":"2024-12-12T12:38:08.344692Z",

Get audit log details, OData queries not support for filtering. Will have to get through graph explorer and copy paste to .txt file.

Sign-In Logs:

Mitigate

Last updated