Office 365的钓鱼攻击这几年出现了一个很明显的趋势单纯靠假登录页骗账号口令的成功率正在下降但只要在域名和认证环节上做手脚绕过MFA也不见得有多难。同形异义字欺骗负责让受害者相信“这是公司那条域名”AiTMAdversary-in-the-Middle中间人攻击负责把受害者的登录会话偷偷截走两者组合起来就能构成一条非常隐蔽的钓鱼链路。这篇文章把我实际搭建实验环境、复现攻击链、做检测还原的过程整理了一遍重点是讲清楚这类攻击为什么能成功、哪些环节可以提前发现以及防御实验里容易踩的坑。适合做邮件安全、身份认证安全或红蓝对抗的朋友参考。1. 为什么把同形异义字和AiTM放在同一个项目里研究1.1 两个攻击思路的交汇点同形异义字欺骗和AiTM看起来是两种独立的攻击手法一个作用于“域名/发件人”另一个作用于“认证会话”。但在真实的钓鱼场景里它们天然互补。同形异义字解决的是“受害者凭什么点进来”的问题AiTM解决的是“即使输入了账号密码并完成MFA攻击者依然能复用会话”的问题。普通钓鱼邮件之所以越来越难生效是因为大家已经被反复教育不要在邮件里点链接、不知道自己密码就绕过、开启MFA后即便泄露密码也没事。安全认知的底线在提高但同形异义字让“看域名”这个动作本身失效了。比如一个西里尔字母的“о”混进普通拉丁字母组成的域名里字体渲染出来几乎一模一样用户如果只看一眼根本分辨不出来。而AiTM通过反向代理方式把受害者导向真实登录服务MFA校验通过后攻击者拿到的是已经被认证过的会话cookie不是一次性的验证码。把这两个技术放在一起研究本质上也是顺着攻击者的视角走先用视觉陷阱降低心理防线再用中间人手法突破MFA防线。两道防线都失守后攻击者手里的不是密码而是一张随时可以进入受害者的Office 365会话的“门票”。1.2 为什么Office 365始终是重灾区Office 365或者说现在的Microsoft 365在企业和学校里的覆盖率实在太高了几乎每个组织都依赖它的邮箱、文档、会议和身份认证。它本身是一个生态而不是单独一个账号一旦被接管攻击者能访问的不只是Outlook还有Teams、SharePoint、OneDrive以及所有绑定了同一身份的其他系统。从攻击者的角度看Office 365还有几个天然有利的条件自定义域名被广泛使用员工习惯用“前缀公司域名”来识别邮件来源组织通常开启了MFA但很多成员对MFA通知验证码的警惕性并不高条件访问策略虽然可以在身份平台侧做处置但并非所有组织都做了严格的设备绑定。加上远程办公常态化员工可能在任意设备、任意网络环境里登录这给AiTM这个“中间人角色”提供了足够多的遮蔽空间。另外Office 365的登录页面本身是标准化的钓鱼页面做起来极其容易模仿。攻击者只需要反代到真实登录地址剩下的一切都由微软自己渲染。这意味着不需要重写界面、不需要伪造SSL证书痕迹只要域名别太离谱用户在视觉上很难找到破绽。1.3 研究目标与适用范围我做这个项目不是想推出一个“新建攻击姿势”而是想回答几个实际问题同形异义字域名在邮件入口处到底能不能被可靠识别AiTM攻击在身份平台侧会留下哪些行为特征如果邮件安全网关和身份平台共同协作能不能在“发给用户的邮件”到“用户登录成功的会话”这条链路上拦下关键步骤。整个实验全部发生在隔离的测试环境里使用了自建本地DNS、测试邮箱域名和模拟用户账号不对外部任何真实系统发起请求。研究结论仅用于安全检测和防护验证供企业内部风险排查时参考。下文中的每一步操作都默认是在有授权的模拟环境中完成的这一点后面还会专门说。2. 同形异义字欺骗攻击拆解2.1 同形异义字/同形字的基础原理同形异义字攻击属于视觉欺骗它利用的是不同文字体系里“长得一模一样”的字符。最典型的是西里尔字母、希腊字母和拉丁字母之间的重叠。例如西里尔的“а”和拉丁的“a”西里尔的“е”和拉丁的“e”西里尔的“о”和拉丁的“o”在大多数常用字体下几乎无法分辨。这类攻击的关键不只是字符本身还包括编码方式。域名系统只接受ASCII字符所以Unicode域名要经过Punycode编码后才能进行DNS解析。比如一个包含非ASCII字符的域名会变成“xn--”开头的字符串。浏览器处理IDN域名时通常会在地址栏把Punycode转换回Unicode方便用户阅读但这也同时在视觉上掩盖了字符差异。不同浏览器的处理策略不一样有的会直接保留Punycode显示有的则把“只包含混合文字且容易混淆”的域名强制显示为Punycode。邮件客户端的情况比浏览器更复杂。有些客户端在显示发件人地址时会用Unicode编码有些则把域名转成Punycode。攻击者可以利用这个不一致性设计一封在发件人姓名上做手脚、在正文链接中使用同形异义字域名的邮件。用户往往只注意到邮件里的品牌名称和正常页面排版根本不会逐个字符去核对域名。2.2 在邮件场景里的利用路径一次典型的同形异义字邮件攻击可以拆成四步选择一个和受害者企业域名非常相似的组织比如把域名里的某个字母替换成同形异义字攻击者注册这个变体域名并部署邮件服务器、钓鱼页面构造一封伪装成系统通知或管理员提醒的邮件发件人地址显示为“管理员admin变体域名”受害者看到发件人名和视觉域名都太像了点击链接后进入钓鱼页面输入账号密码。这里有一个细节邮件网关往往会对发件域名做SPF、DKIM和DMARC校验。攻击者如果想通过校验就得在变体域名上正确配置这些DNS记录。但由于变体域名通常是与目标域名同级别的私有域名攻击者完全可以合法地为自己的域名配置SPF和DKIM。也就是说邮件安全验证不是看“这个域名是不是和别人类似”而是看“这个域名是否为自己所有”所以同形异义字攻击天然能绕过传统的邮件源验证。更有意思的是攻击者可以使用同形异义字域名来接收“验证邮件”或者“密码重置邮件”。只要目标系统没有做域名相似度检查攻击者就可以用这个变体邮箱注册同品牌服务从而制造更逼真的假账号。这在攻击链上很常见也是我在实验里验证过的一个分支。2.3 复现实验从域名到访问入口为了避免在公网上注册任何类似真实品牌的域名实验用的是本地私有DNS和完全虚构的测试域名。我们把一个测试域名里的拉丁字母“e”替换为西里尔字母“е”然后用Python的IDNA库观察这个域名在编码后的变化。import idna original test.com fake tеst.com # 这里第二个字符是西里尔字母е不是拉丁字母e print(idna.encode(original).decode()) print(idna.encode(fake).decode())输出结果中普通域名保持“test.com”而变体域名会转成“xn--”开头的一段Punycode。这就很直观地说明了问题在用户眼里浏览器或邮件客户端可能会把“xn--tst-xxx.com”还原成了带西里尔字母的“tеst.com”视觉上和真正的“test.com”没有区别但二者在DNS层面是绝对不同的两个域名。我还在本地搭建了一个仅有内网可达的邮箱服务用这个变体域名给测试用户发了一封纯文本邮件。在Outlook客户端里发件人地址中的西里尔字母几乎无法被分辨特别是在系统字体环境下。如果不把字体放大到200%肉眼基本看不出差异。所以用户层面的防御只能作为最后一道辅助手段邮件网关侧的域名相似度检测才是更可靠的拦截点。3. AiTM钓鱼攻击原理与“绕过MFA”的本质3.1 传统钓鱼为什么过不了MFA传统钓鱼页面只做一个动作存储用户输入的账号密码。攻击者拿到口令后尝试登录目标系统却被MFA拦下。因为MFA要求提供一次性验证码或Biometric验证攻击者手里没有所以即使拿到密码也进不去。所以很多组织只要开启了MFA就默认“口令泄露也可以接受”。但AiTM攻击打破了这个假设。它的做法是在攻击服务器上运行一个反向代理将所有来自受害者的请求转发给真实的Office 365登录服务再把真实服务返回的响应转发回受害者。受害者在钓鱼页面输入账号、密码、验证码的时候实际上是在和真实登录服务交互。MFA验证码没有“错发给攻击者”而是被真实服务正确验证了区别只是攻击者同时也在通信链路中捕获了登录成功后下发的会话cookie。拿到这个cookie之后攻击者的浏览器只需要替换一下会话标识就能直接进入受害者的邮箱而无需再次认证。MFA校验的是“登录时候的用户身份”但后续的每一个请求都只认会话cookie。AiTM攻击瞄准的正是这个认证与授权之间的连接点。3.2 攻击链的完整流程在实际模拟中攻击链基本上是这样走的阶段动作对应的检测点1攻击者部署同形异义字域名和反向代理页面域名相似度、域名年龄2发送钓鱼邮件给目标用户邮件正文链接分析、发件域名信誉3受害者点击链接访问代理页面登录页URL、证书信息4受害者输入账号密码并完成MFA异常登录时间、IP信誉、UA可疑5代理转发请求并获得会话cookie会话创建后的异常访问行为6攻击者使用cookie访问邮箱和云盘同时段多地登录、设备指纹突变传统钓鱼在第三步、第四步就被MFA挡住了AiTM则会一直走到第六步。因此检测策略不能在“输入密码”这一个点下功夫而要把视野放到“登录成功后的一系列会话行为”上。3.3 在同形异义字域名基础上组合单独使用AiTM时最大的风险是受害者对链接域名产生怀疑。如果攻击者直接把真实域名的变体字符串放在链接里很多用户还是能分辨出来。而同形异义字恰好把这个最大的风险点抹掉了。组合后的攻击场景是受害者收到域名几乎一样的发件人邮件点击链接后进入一个SSL证书有效、页面和Office 365登录页完全相同的钓鱼页面。此时受害者无论是检查URL、查看地址栏还是回忆“公司登录系统长什么样”都没法得出“这是钓鱼”的结论。输入密码后手机弹出MFA验证码受害者确认后以为自己完成了正常登录甚至会被导向真实的应用界面。攻击者在这个过程中的投入很低但对安全运营团队来说识别这种组合攻击需要同时打开邮件检测、身份检测和行为分析的开关单独部署任何一个单向产品都可能漏掉关键点。4. 实验环境与模拟过程4.1 环境与基础设施准备模拟实验环境不需要太大但每个组件都要能独立控制。我的实验环境划分成四块本地DNS服务器负责将变体域名的解析结果指向本机不向公网暴露任何记录测试邮件服务器用于发送模拟钓鱼邮件只对内网用户开放中间人代理节点部署在另一台虚拟机上配置为反向代理到真实登录服务的测试租户目标账号与MFA工具在Office 365测试租户里创建了专属测试账号并绑定了验证器应用。这里要特别强调一点模拟攻击时中间人代理所指向的目标必须是完全自控的测试租户。如果引用真实企业或个人的账号即使只是测试“点击一下”也超出了正当授权范围。这个边界是整个实验的前提。4.2 模拟攻击的详细步骤整个复现过程分五步进行。第一步是构造变体域名。我在本地DNS中加入一条A记录把包含西里尔字母的变体域名解析到代理服务器IP。由于内网环境不连接外部DNS所有访问都不会触达真实网络这一步完全可控。第二步是搭建代理页面。代理核心逻辑很简单拦截HTTP请求将Host和路径映射到真实登录地址同时读取目标服务器返回的Cookie标记并记录下来。我没有使用任何现成的商业钓鱼工具而是写了一个精简的转发脚本完全是为了观察会话cookie的生命周期。第三步是发送钓鱼邮件。测试邮件模拟了企业内部“安全通知”场景邮件正文含有一个链接链接上的域名就是变体域名。我故意关闭了外发限制让测试账号能正常收到这封邮件便于观察邮件客户端对发件域名的展示方式。第四步是模拟受害者登录。在浏览器中打开链接地址栏确实能显示安全锁图标页面上的Office 365品牌标识也完全由真实服务渲染看不出任何明显的页面代码痕迹。输入测试账号密码并点击MFA确认后浏览器跳转到了真实的应用首页。第五步是提取会话并验证。代理脚本在转发过程中记录到的Cookie值导出后放到一个新的浏览器会话里。测试结果显示不需要重新输入密码和MFA就能直接访问测试邮箱首页。这验证了“MFA被通过但会话被截获”的完整闭环。4.3 关键观测点模拟过程中有几个现象很值得记录。第一个是MFA通知的显示。用户手机上的验证器应用会显示一个正常登录请求包括IP和登录地点。由于测试环境使用了本地网络这个IP显示会与平时办公网络不同。如果目标组织配置了登录风险检测这一步可能会触发提示但很多用户仍然会点击“允许”因为他们认为自己刚刚就是在主动登录系统。第二个是会话cookie的时长。不同会话类型和认证方式的Cookie有效期差别很大有些甚至能持续数小时。攻击者只要在这段时间内使用就能长期保持对目标会话的访问。因此“会话失效时间”也是防御端一个重要参数。第三个是浏览器指纹变化。代理服务器和真实浏览器之间会有UA、Accept-Language等方面的细微差异。虽然普通用户察觉不到但对于监测系统来说同一个会话在短时间内从“内部办公网IP”切换到“云上跳板IP”这就是一个非常典型的异常信号。5. 检测与防御实践5.1 在邮件入口识别同形异义字传统邮件安全网关对“同形异义字域名”几乎没有感知因为这并不属于病毒库或恶意域名库。比较有效的做法是针对“相似域名”建立监听策略。我在实验里测试过一种简单方法把所有入站邮件中的发件域名转换成Punycode并提取其中的Unicode字符集类型。如果发现同一个域名中混合了拉丁字母和西里尔字母或者拉丁字母与希腊字母混用就标记为高风险。这个规则的检测命中率比较稳定误报主要集中在一类场景很多国际公司本身会在域名中使用中文或特殊拼音字符比如点“中文.com”这种域名所以规则还要和组织的品牌域名白名单配合。以下是采集域名文字特征的最小化示例不是完整产品但可以帮助理解检测思路def contains_mixed_scripts(domain): import unicodedata scripts set() for ch in domain: try: scripts.add(unicodedata.name(ch).split( )[0]) except ValueError: pass return len(scripts) 1这个函数会把“LATIN、CYRILLIC”等脚本类别提取出来。如果发件域名同时包含拉丁和西里尔字符返回值就是True。可以直接在邮件网关的自定义过滤规则里调用。同时还要监控“新注册的相似域名”。不少企业会购买和自己品牌名接近的域名但攻击者也可以注册。建议内部建立品牌关键词表对包含品牌名和常见混淆字符的域名做主动探测定时检查Whois的注册时间和注册商。域名注册时间少于30天、注册人和企业没有关联、邮件服务器配置反常这些都是高风险标签。5.2 在身份层对抗AiTM身份层对抗AiTM的核心原则是不要让“密码一次性验证码”成为会话的唯一信任锚点。第一尽量启用更强绑定的身份验证方式。只依赖短信或验证器应用的MFA在AiTM场景下是脆弱的因为验证码只是用户侧的证明最终还是会转化为HTTP层的会话。Phishing-resistant认证方式比如FIDO2密钥或内置平台密钥能通过绑定的源信息识别当前访问是否来自受保护的应用。如果组织条件允许至少要对管理员账号和高权限业务账号启用这类方式。第二启用条件访问策略中的设备状态要求。常见的做法是“要求设备标记为合规设备”或者“要求设备已加入域”。有了设备状态约束后攻击者即使拿到会话cookie也会因为设备不是合规对象而被拒绝访问。这个策略对阻断AiTM非常有效因为中间人代理很难同时伪装成合法设备。第三关闭旧版认证协议。很多组织的数据泄露不是来自现代认证而是来自IMAP/POP、基础认证等旧协议。攻击者拿到口令之后用旧协议请求就能绕过MFA。关闭旧协议后所有访问都会走现代认证流程便于身份平台统一审计。第四做好会话登录异常检测。不要把注意力只放在首次登录上也要看登录后的行为下载大量邮件、创建转发规则、批量访问OneDrive文件、从异常IP发起邮件发送等。一旦发现“同一个会话在不同地点同时活动”应立即失效该会话并强制重新认证。5.3 用户侧的识别技巧用户侧不能作为唯一防线但也要让员工具备基本辨别力。比较实用的几个技巧包括在浏览器地址栏中点击锁形图标查看实际域名优先看域名是否以“xn--”开头用密码管理器自动填充登录表单因为密码管理器会在域名不匹配时拒绝填充这是一个非常高效的防钓鱼提醒收到邮件时先用鼠标悬停查看链接目标不要只凭发件人显示名称判断登录页面如果要求输入密码后又要求输入MFA验证码回到官方App或浏览器地址栏手动输入域名不要通过邮件里的链接进入。我在实际测试中发现用户经过这种简单培训后对“同形异义字”邮件的点击率有明显下降。但要注意这类的培训必须用模拟邮件反复验证而不是只讲一遍PPT。因为人的视觉记忆会疲惫只有形成“看域名底层、看链接目标”的肌肉记忆才有效。6. 典型问题与排查实录6.1 复现过程中的几个坑第一个坑是邮件客户端渲染差异。不同版本Outlook对Unicode域名的显示策略差别很大。有些版本在邮件头中会把IDN域名强制转成Punycode显示比如“xn--tst-xxx.com”这样攻击效果就会大打折扣。但另一些版本则会把Punycode还原成Unicode并叠加上好看的字体看起来更隐蔽。所以测试时不要在单一客户端得出“无效”的结论要在Web端、桌面端和移动端分别看一遍。第二个坑是MFA审批通知和代理转发的时序问题。部分环境下代理服务器默认不会等待MFA响应完全返回再提取Cookie切得早了可能只拿到未认证的临时Cookie。需要调整反向代理的超时参数确保完整通信后再读取会话。这个细节如果不注意很容易出现“能登录但拿不到有效会话”的假阴性。第三个坑是Office 365登录页有时候会触发额外挑战比如“选择账号位置”或“证明你是一个人”。在模拟代理过程中这些额外的交互需要代理配置文件做相应映射。如果代理没有处理这些子请求用户会在页面卡住从而发现异常。这类情况虽然增加了攻击者的成本但同时也能成为检测点一个正常内网用户不太可能在登录时频繁出现额外验证码。6.2 误报与漏报把同形异义字检测直接上线后误报主要来自跨国企业本身使用多语言域名。比如有些组织会为“某公司.cn”和“某公司.com”同时配置邮箱并允许员工在外部邮件里使用中文域名。如果域名中包含中西混合字符规则就会误判。解决方法是建立内部域名的“受信任域名字典”只有域名的Unicode脚本组合与字典里的特征不一致时才告警。漏报则主要来自同形异义字不只是字母替换还有“数字和字母混淆”比如数字“0”和字母“O”。这类字符完全在ASCII范围内不受Unicode脚本检测规则约束。要覆盖它们必须引入视觉相似度算法比如用一个字符在常见字体下的视觉相似度矩阵做归一化计算。这也是当前主流邮件网关大多采用“模糊匹配品牌域名监听”相结合的原因。6.3 研究伦理与合规边界这一点值得单独拿出来说。复现同形异义字和AiTM攻击本质上是在还原一个可能被恶意利用的攻击链。正因如此实验环境必须完全隔离测试账号必须完全可控所有操作记录必须保留最后及时清理环境。没有授权就对外部系统发起任何形式的探测哪怕是发送一封测试邮件都是不可接受的行为。我习惯在每个项目开始前把测试范围、时间窗口、涉及域名和账号清单写成一份模拟授权书并交由项目组确认。这样能让所有人都清楚边界在哪里。研究攻击不是为了制造恐慌而是为了让邮件安全网关、身份平台和用户意识这三道防线能更有效地联动。最后再分享一点个人体会这套实验做完之后我最深的感受是当下的攻击者已经很少和你拼“谁的页面做得更像”而是直接在认证链路里找一个可以长期蹲守的位置。同形异义字解决的是视觉判断问题AiTM解决的是会话信任问题两者结合起来受害者的每次点击都可能变成一次真实的身份接管。防御上不要指望某一种单点产品能一劳永逸。邮件网关负责挡掉“看起来不对劲的域名”身份平台负责卡住“来历不明的会话”用户意识负责降低“不加思考就点链接”的概率。只有这三层都做扎实面对这类攻击时才有还手之力。后续有条件的话我会继续把这个实验扩展到异常会话行为分析上把“会话被创建后发生的一系列动作”也纳入监测范围那样检测闭环会更完整。