Implements passwordless authentication using Microsoft Entra ID with FIDO2 security keys, Windows Hello for Business, Microsoft Authenticator passkeys, and certificate-based auth to eliminate password attacks. Useful for passwordless deployments, FIDO2 config, phishing-resistant MFA, or Entra auth policies.
npx claudepluginhub killvxk/cybersecurity-skills-zhThis skill uses the workspace's default tool permissions.
- 组织希望消除基于密码的攻击(钓鱼、凭据填充、暴力破解)
Implements passwordless authentication using Microsoft Entra ID with FIDO2 security keys, Windows Hello for Business, Microsoft Authenticator passkeys, and certificate-based auth to eliminate password attacks.
Configures passwordless authentication in Microsoft Entra ID with FIDO2 keys, Windows Hello for Business, passkeys, and certificates to block password attacks and enable phishing-resistant MFA.
Deploys FIDO2/WebAuthn passwordless authentication with security keys, platform authenticators, passkeys, and biometrics. Covers WebAuthn API integration, server config, and NIST SP 800-63B AAL3-compliant migration.
Share bugs, ideas, or general feedback.
不适用于无法支持现代认证协议的环境;使用 NTLM 或基本认证的旧版应用程序必须先完成迁移。
在 Microsoft Entra 中启用无密码认证方法:
# 连接到 Microsoft Graph
Connect-MgGraph -Scopes "Policy.ReadWrite.AuthenticationMethod", "User.ReadWrite.All"
# 启用 FIDO2 安全密钥认证方法
$fido2Policy = @{
"@odata.type" = "#microsoft.graph.fido2AuthenticationMethodConfiguration"
state = "enabled"
isAttestationEnforced = $true
isSelfServiceRegistrationAllowed = $true
keyRestrictions = @{
isEnforced = $true
enforcementType = "allow"
aaGuids = @(
"cb69481e-8ff7-4039-93ec-0a2729a154a8", # YubiKey 5 系列
"ee882879-721c-4913-9775-3dfcce97072a", # YubiKey 5 NFC
"fa2b99dc-9e39-4257-8f92-4a30d23c4118", # YubiKey 5C NFC
"2fc0579f-8113-47ea-b116-bb5a8db9202a", # YubiKey Bio
"73bb0cd4-e502-49b8-9c6f-b59445bf720b" # Google Titan
)
}
includeTargets = @(
@{
targetType = "group"
id = "all_users" # 或特定安全组 ID
}
)
}
Update-MgPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration `
-AuthenticationMethodConfigurationId "fido2" `
-BodyParameter $fido2Policy
# 启用支持通行密钥的 Microsoft Authenticator
$authenticatorPolicy = @{
"@odata.type" = "#microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration"
state = "enabled"
featureSettings = @{
displayAppInformationRequiredState = @{
state = "enabled"
includeTarget = @{
targetType = "group"
id = "all_users"
}
}
displayLocationInformationRequiredState = @{
state = "enabled"
includeTarget = @{
targetType = "group"
id = "all_users"
}
}
companionAppAllowedState = @{
state = "enabled"
}
}
includeTargets = @(
@{
targetType = "group"
id = "all_users"
authenticationMode = "any"
}
)
}
Update-MgPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration `
-AuthenticationMethodConfigurationId "microsoftAuthenticator" `
-BodyParameter $authenticatorPolicy
# 启用 Windows Hello for Business
$whfbPolicy = @{
"@odata.type" = "#microsoft.graph.windowsHelloForBusinessAuthenticationMethodConfiguration"
state = "enabled"
pinMinimumLength = 6
pinMaximumLength = 127
pinLowercaseCharactersUsage = "allowed"
pinUppercaseCharactersUsage = "allowed"
pinSpecialCharactersUsage = "allowed"
securityKeyForSignIn = "enabled"
includeTargets = @(
@{
targetType = "group"
id = "all_users"
}
)
}
Update-MgPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration `
-AuthenticationMethodConfigurationId "windowsHelloForBusiness" `
-BodyParameter $whfbPolicy
Write-Host "无密码认证方法已成功启用"
创建要求抗钓鱼认证的条件访问策略:
# 为抗钓鱼 MFA 创建自定义认证强度
$authStrength = @{
displayName = "抗钓鱼无密码"
description = "要求 FIDO2、WHfB 或基于证书的认证"
allowedCombinations = @(
"fido2",
"windowsHelloForBusiness",
"x509CertificateMultiFactor"
)
requirementsSatisfied = "mfa"
}
$strengthPolicy = New-MgPolicyAuthenticationStrengthPolicy -BodyParameter $authStrength
# 创建要求抗钓鱼认证的条件访问策略
$caPolicy = @{
displayName = "所有应用要求抗钓鱼认证"
state = "enabledForReportingButNotEnforced" # 从仅报告模式开始
conditions = @{
users = @{
includeUsers = @("All")
excludeGroups = @("Passwordless-Exclusion-Group")
}
applications = @{
includeApplications = @("All")
}
clientAppTypes = @("browser", "mobileAppsAndDesktopClients")
}
grantControls = @{
operator = "OR"
authenticationStrength = @{
id = $strengthPolicy.Id
}
}
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $caPolicy
# 为管理员门户创建更严格的策略
$adminPolicy = @{
displayName = "管理员访问要求安全密钥"
state = "enabled"
conditions = @{
users = @{
includeRoles = @(
"62e90394-69f5-4237-9190-012177145e10", # 全局管理员
"194ae4cb-b126-40b2-bd5b-6091b380977d", # 安全管理员
"f28a1f50-f6e7-4571-818b-6a12f2af6b6c", # SharePoint 管理员
"29232cdf-9323-42fd-ade2-1d097af3e4de" # Exchange 管理员
)
}
applications = @{
includeApplications = @(
"797f4846-ba00-4fd7-ba43-dac1f8f63013", # Azure 门户
"00000006-0000-0ff1-ce00-000000000000", # Microsoft 365 管理
"0000000a-0000-0000-c000-000000000000" # Entra 管理中心
)
}
}
grantControls = @{
operator = "OR"
authenticationStrength = @{
id = $strengthPolicy.Id
}
}
sessionControls = @{
signInFrequency = @{
value = 4
type = "hours"
isEnabled = $true
}
}
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $adminPolicy
通过 Microsoft Intune MDM 配置 WHfB 部署:
# 在 Intune 中创建 Windows Hello for Business 配置文件
$whfbProfile = @{
"@odata.type" = "#microsoft.graph.windowsIdentityProtectionConfiguration"
displayName = "WHfB - 企业部署"
description = "适用于所有托管设备的 Windows Hello for Business 配置"
useSecurityKeyForSignin = $true
windowsHelloForBusinessBlocked = $false
pinMinimumLength = 6
pinMaximumLength = 127
pinUppercaseCharactersUsage = "allowed"
pinLowercaseCharactersUsage = "allowed"
pinSpecialCharactersUsage = "allowed"
enhancedAntiSpoofingForFacialFeaturesEnabled = $true
pinRecoveryEnabled = $true
securityDeviceRequired = $true # 要求 TPM
unlockWithBiometricsEnabled = $true
useCertificatesForOnPremisesAuthEnabled = $true # 混合场景
# 混合加入的 Cloud Kerberos Trust(推荐替代密钥信任)
windowsHelloForBusinessAuthenticationMethod = "cloudKerberosTrust"
}
# 创建配置文件
$profile = New-MgDeviceManagementDeviceConfiguration -BodyParameter $whfbProfile
# 分配给所有 Windows 设备
$assignment = @{
target = @{
"@odata.type" = "#microsoft.graph.allDevicesAssignmentTarget"
}
}
New-MgDeviceManagementDeviceConfigurationAssignment `
-DeviceConfigurationId $profile.Id `
-BodyParameter $assignment
# 配置 Cloud Kerberos Trust(用于混合 Azure AD 加入设备)
# 无需 PKI 基础设施
Import-Module AzureADHybridAuthenticationManagement
$domain = "corp.local"
$cloudCredential = Get-Credential -Message "输入 Azure AD 全局管理员凭据"
$domainCredential = Get-Credential -Message "输入本地域管理员凭据"
Set-AzureADKerberosServer `
-Domain $domain `
-CloudCredential $cloudCredential `
-DomainCredential $domainCredential
Get-AzureADKerberosServer -Domain $domain -CloudCredential $cloudCredential `
-DomainCredential $domainCredential
Write-Host "已为混合 WHfB 部署配置 Cloud Kerberos Trust"
实施安全密钥注册工作流:
# 通过临时访问通行证批量注册 FIDO2 安全密钥
function Issue-TemporaryAccessPass {
param(
[string]$UserId,
[int]$LifetimeMinutes = 60,
[bool]$IsUsableOnce = $true
)
$tap = @{
"@odata.type" = "#microsoft.graph.temporaryAccessPassAuthenticationMethod"
lifetimeInMinutes = $LifetimeMinutes
isUsableOnce = $IsUsableOnce
}
$result = New-MgUserAuthenticationTemporaryAccessPassMethod `
-UserId $UserId `
-BodyParameter $tap
return @{
UserId = $UserId
TemporaryAccessPass = $result.TemporaryAccessPass
ExpiresAt = $result.CreatedDateTime.AddMinutes($LifetimeMinutes)
}
}
# 批量发放临时访问通行证用于安全密钥注册活动
$registrationUsers = Import-Csv "security_key_registration_list.csv"
$tapResults = foreach ($user in $registrationUsers) {
$tap = Issue-TemporaryAccessPass -UserId $user.UserPrincipalName
[PSCustomObject]@{
User = $user.UserPrincipalName
TAP = $tap.TemporaryAccessPass
Expires = $tap.ExpiresAt
KeySerial = $user.AssignedKeySerial
}
}
$tapResults | Export-Csv "tap_assignments.csv" -NoTypeInformation
# 监控 FIDO2 注册进度
function Get-Fido2RegistrationStatus {
$allUsers = Get-MgUser -All -Property "id,userPrincipalName,department"
$registrationStatus = foreach ($user in $allUsers) {
$methods = Get-MgUserAuthenticationFido2Method -UserId $user.Id
[PSCustomObject]@{
UserPrincipalName = $user.UserPrincipalName
Department = $user.Department
Fido2KeyCount = $methods.Count
KeyModels = ($methods.Model -join ", ")
RegistrationDates = ($methods.CreatedDateTime -join ", ")
HasBackupKey = $methods.Count -ge 2
}
}
return $registrationStatus
}
$status = Get-Fido2RegistrationStatus
$total = $status.Count
$registered = ($status | Where-Object { $_.Fido2KeyCount -gt 0 }).Count
$withBackup = ($status | Where-Object { $_.HasBackupKey }).Count
Write-Host "FIDO2 注册进度"
Write-Host " 用户总数:$total"
Write-Host " 已注册: $registered ($([math]::Round($registered/$total*100,1))%)"
Write-Host " 有备用密钥:$withBackup ($([math]::Round($withBackup/$total*100,1))%)"
逐步淘汰可被钓鱼的认证因素:
# 禁用短信和语音电话认证
$smsPolicy = @{
"@odata.type" = "#microsoft.graph.smsAuthenticationMethodConfiguration"
state = "disabled"
}
Update-MgPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration `
-AuthenticationMethodConfigurationId "sms" `
-BodyParameter $smsPolicy
$voicePolicy = @{
"@odata.type" = "#microsoft.graph.voiceAuthenticationMethodConfiguration"
state = "disabled"
}
Update-MgPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration `
-AuthenticationMethodConfigurationId "voice" `
-BodyParameter $voicePolicy
# 通过条件访问阻止旧版认证协议
$blockLegacyPolicy = @{
displayName = "阻止旧版认证"
state = "enabled"
conditions = @{
users = @{ includeUsers = @("All") }
applications = @{ includeApplications = @("All") }
clientAppTypes = @(
"exchangeActiveSync",
"other"
)
}
grantControls = @{
operator = "OR"
builtInControls = @("block")
}
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $blockLegacyPolicy
# 审计仍在使用旧版认证的用户
$legacyAuthReport = Get-MgAuditLogSignIn -Filter "clientAppUsed ne 'Browser' and clientAppUsed ne 'Mobile Apps and Desktop clients'" `
-Top 1000 | Group-Object userPrincipalName | Select-Object Count, Name |
Sort-Object Count -Descending
Write-Host "使用旧版认证的用户(最近 30 天):"
$legacyAuthReport | Format-Table -AutoSize
跟踪部署进度和认证方法使用情况:
# 生成无密码采用仪表板数据
function Get-PasswordlessAdoptionMetrics {
$registrationReport = Get-MgReportAuthenticationMethodUserRegistrationDetail -All
$metrics = @{
TotalUsers = $registrationReport.Count
PasswordlessCapable = ($registrationReport | Where-Object { $_.IsPasswordlessCapable }).Count
MfaRegistered = ($registrationReport | Where-Object { $_.IsMfaRegistered }).Count
Fido2Registered = ($registrationReport | Where-Object { "fido2" -in $_.MethodsRegistered }).Count
WhfbRegistered = ($registrationReport | Where-Object { "windowsHelloForBusiness" -in $_.MethodsRegistered }).Count
AuthenticatorRegistered = ($registrationReport | Where-Object { "microsoftAuthenticator" -in $_.MethodsRegistered }).Count
SmsOnly = ($registrationReport | Where-Object {
"sms" -in $_.MethodsRegistered -and
"fido2" -notin $_.MethodsRegistered -and
"windowsHelloForBusiness" -notin $_.MethodsRegistered
}).Count
}
$signInLogs = Get-MgAuditLogSignIn -Top 10000 -Filter "createdDateTime ge $((Get-Date).AddDays(-30).ToString('yyyy-MM-ddTHH:mm:ssZ'))"
$authMethodUsage = $signInLogs |
Group-Object { $_.AuthenticationMethodsUsed -join "," } |
Select-Object Count, Name | Sort-Object Count -Descending
return @{
Registration = $metrics
Usage = $authMethodUsage
}
}
$adoption = Get-PasswordlessAdoptionMetrics
$reg = $adoption.Registration
Write-Host "无密码采用报告"
Write-Host "============================"
Write-Host "用户总数: $($reg.TotalUsers)"
Write-Host "无密码能力: $($reg.PasswordlessCapable) ($([math]::Round($reg.PasswordlessCapable/$reg.TotalUsers*100,1))%)"
Write-Host " FIDO2 密钥: $($reg.Fido2Registered)"
Write-Host " Windows Hello: $($reg.WhfbRegistered)"
Write-Host " Authenticator: $($reg.AuthenticatorRegistered)"
Write-Host "MFA 已注册: $($reg.MfaRegistered) ($([math]::Round($reg.MfaRegistered/$reg.TotalUsers*100,1))%)"
Write-Host "仅短信(需要升级): $($reg.SmsOnly)"
| 术语 | 定义 |
|---|---|
| FIDO2 | 快速身份在线 2 标准,使用绑定到硬件认证器或平台凭据的公钥密码学实现无密码认证 |
| 通行密钥(Passkey) | 可以绑定到设备(安全密钥)或跨设备同步的 FIDO2 凭据,无需密码即可提供抗钓鱼认证 |
| Windows Hello for Business | 使用 PIN、指纹或面部识别的 Windows 平台认证器,由 TPM 保护的非对称密钥支持无密码登录 |
| Cloud Kerberos Trust | 混合 WHfB 的部署模型,使用 Azure AD Kerberos 访问本地资源,无需 PKI 证书基础设施 |
| 临时访问通行证 | 管理员颁发的限时密码,使用户能够注册无密码方法或在主要方法不可用时恢复访问 |
| 认证强度 | Microsoft Entra 中的条件访问功能,指定哪些认证方法组合满足给定策略的 MFA 要求 |
背景:一个拥有 5,000 名用户的组织计划在 12 个月内消除密码,此前经历了一次入侵 47 个账户的钓鱼攻击。当前状态:60% 使用短信 MFA,30% 使用 Authenticator 应用,10% 没有 MFA。
处理方式:
注意事项:
无密码认证部署报告
================================================
租户: corp.onmicrosoft.com
用户: 5,247
部署阶段: 第四阶段(Authenticator 通行密钥)
认证方法注册
无密码能力: 4,103 / 5,247 (78.2%)
FIDO2 安全密钥: 892 (17.0%)
Windows Hello: 2,847 (54.3%)
Authenticator 通行密钥:1,234 (23.5%)
基于证书: 312 (5.9%)
旧版方法状态
仅短信用户: 387 (7.4%) -- 迁移中
仅语音用户: 0(已禁用)
无 MFA 用户: 42 (0.8%) -- 已发放临时访问通行证
条件访问
抗钓鱼策略: 已强制执行(除排除组外的所有用户)
旧版认证阻止: 已启用
管理员门户策略: 需要安全密钥
登录分析(最近 30 天)
总登录次数: 847,293
无密码: 623,891 (73.6%)
密码 + MFA: 198,402 (23.4%)
仅密码: 0(已阻止)
旧版协议: 0(已阻止)
安全影响
钓鱼事件: 0(部署前 47 次)
密码重置工单: -82% 减少
平均登录时间: 8.2 秒(无密码)vs 24.1 秒(密码)