← 中文资源

简体中文版本

MFA 疲劳攻击

MFA 疲劳攻击向受害者轰炸推送审批,直到误触或为了止噪而点下同意,把强因子变成社工通道。

阅读英文原文

概念定义

第二因子本身成了杠杆:推送足够多的提示,总有一次被批准。用户为了让手机停止震动而点同意,或相信“客服”所说的例行验证。认证模型没有坏,坏的是那个人的决策点。

工作机制

持有有效凭据的攻击者反复发起认证触发通知。防御:数字匹配(要求用户输入登录屏幕显示的码)、审批限速与锁定、展示请求来源的上下文提示、管理员迁移到硬件安全密钥等防钓鱼因子。

使用场景

一切基于推送的 MFA 面,特权账号优先。技术控制要配合客服政策:身份验证流程绝不包含“批准一个意外提示”。

常见误区

“推送 MFA 比 SMS 弱”是误判——因子没问题,审批交互才是攻击面,数字匹配即可关闭。对每次提示都告警只会训练用户更快划掉通知;重试无限次等于给脚本轰炸开绿灯。数字匹配在攻击者同时控制显示码的屏幕时会退化;限速必须配账号级锁定,又不能变成对已知用户的拒绝服务武器。

代码示例

export function escapeRegExp(input) {
  if (typeof input !== "string") throw new TypeError("input must be a string");
  return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

export function literalRegExp(input, flags = "") {
  if (typeof flags !== "string") throw new TypeError("flags must be a string");
  if (/[gy]/.test(flags)) {
    throw new RangeError("stateful flags g and y are not allowed");
  }
  return new RegExp(escapeRegExp(input), flags);
}
package main

import (
	"crypto/sha256"
	"crypto/subtle"
	"fmt"
)

func ConstantTimeEqual(a, b string) bool {
	left := sha256.Sum256([]byte(a))
	right := sha256.Sum256([]byte(b))
	return subtle.ConstantTimeCompare(left[:], right[:]) == 1
}

func main() {
	secret := "s3cr3t-token"
	fmt.Println(ConstantTimeEqual(secret, "s3cr3t-token"))
	fmt.Println(ConstantTimeEqual(secret, "s3cr3t-tokeX"))
	fmt.Println(ConstantTimeEqual(secret, "short"))
}