
浏览器内浏览器攻击机制与防御研究当钓鱼窗口长在主窗口里你该如何识别与对抗刚入行做安全运营那几年我处理最多的告警就是凭据窃取而其中七成以上来自同一种套路受害者看到一个长得几乎一模一样的弹窗然后输入了账号密码。后来这个套路有了正式的名字——浏览器内浏览器攻击Browser-in-the-Browser下文简称 BiB。它不像传统的 N-day 漏洞那样直接攻破浏览器内核而是利用用户对“浏览器信任体系”的天然信任在一个合法页面里伪造出另一个“合法浏览器窗口”。你看到的域名、锁形图标、地址栏、证书身份都是假的但用户完全无法分辨。这篇文章想和你聊透三件事BiB 攻击到底怎么运作为什么它能绕过人的肉眼甚至部分安全产品以及我们在终端、Web 应用和用户意识三个层面到底能用什么办法防住它。无论你是安全运营、Web 开发者还是只想保护自己账号的普通用户下面这些内容都能直接用上。1. 攻击机制拆解为什么一个弹窗能骗过所有人1.1 BiB 攻击的底层逻辑模拟的不是窗口是信任BiB 的杀伤力不在代码而在心理学。它的核心是把一个攻击者构造的“伪浏览器窗口”嵌入或叠加在合法页面之上。这个伪窗口不是真的浏览器 UI而是用 HTML/CSS/JavaScript 画出来的但它高度还原了真实浏览器窗口的关键视觉元素地址栏、标签页、锁形图标、甚至页面内的鼠标右键菜单。想象一下你正在用自己常去的某家银行网银页面地址栏清清楚楚写着https://bank.example.com窗口右上角还有一个小锁。这时候弹出一个新的浏览器窗口里面要求你重新登录地址栏还是同一个域名锁也在。你输入了账号和密码然后页面卡住了你以为网络慢刷新后发现账号里的钱没了。但实际上那个弹窗从头到尾都是主页面里一个绝对定位的div只是它把周围真实浏览器的边框伪装得恰到好处让你误以为它是另一个独立窗口。这种攻击依赖的关键技术点有三个弹窗生成能力、样式伪造能力、交互欺骗能力。弹窗可以用window.open()或自定义 DOM 层实现样式伪造靠 CSS 模拟浏览器边框、地址栏、按钮交互欺骗则通过事件劫持让键盘输入落入攻击者的表单。整个过程不需要任何漏洞不需要绕过内存保护只需要你想让用户看到什么他大概率就会看到什么。1.2 与普通钓鱼的区别从“仿冒站点”到“仿冒浏览器”传统钓鱼建设一个独立的钓鱼站点用户访问的地址栏是一个完全不同或相似度极高的域名比如faceb00k.com。这类攻击的经验防御法则是“看清楚域名”。而 BiB 把整个伪造窗口渲染在合法页面内部地址栏显示的是真实网站域名用户习惯性信任当前页面的上下文从而放松对“窗口是否真实”的检查。用一句话概括两者的区别传统钓鱼让你访问一个假网站BiB 让你在一个真网站里看到一个假窗口。从攻击成本看BiB 的复制度更高但只要有一份被模仿网站的静态资源几分钟就能拼出一个以假乱真的弹窗。这也是我在实际项目中看到 BiB 从概念验证PoC走向量产的根本原因。之前很多进攻方不愿意做因为要手工写大量 JavaScript 凑窗口细节现在前端模板、UI 框架、低代码生成工具满天飞复制一套浏览器 UI 样式比复制一个支付页面还容易。2. 凭证窃取路径与攻击场景谁最容易中招又是怎么中的2.1 从 OAuth 授权窗口到第三方登录劫持这里必须点名一个高危场景OAuth 第三方登录。当你点击网站的“使用 Facebook 账号登录”正常情况下会弹出一个小窗口让你输入 Facebook 账号密码并授权。这个窗口的域名是facebook.com浏览器地址栏清晰可见。BiB 攻击最常复制的就是这种授权弹窗。攻击流程大致是这样攻击者先制作一个伪造的 OAuth 授权弹窗弹窗里的“Facebook 登录界面”像素级还原真实页面然后把这段代码注入目标页面。用户访问了某个被攻陷或恶意设计的站点点击“使用 Facebook 登录”伪窗口弹出输入凭证点击确定。凭证被捕获后攻击者要么直接登录受害者的 Facebook 账号要么继续利用该账号发起更多社工攻击。我在测试一个企业级安全产品时专门复现过这个场景。当时我们用一个模拟 OAuth 页面的 PoC让二十名安全工程师参与识别测试。结果只有三位在输入密码前意识到地址栏无法下拉、标签页不能点击其他人全部中招。这里面包括我自己——第一次见到时也需要花几秒钟确认眼前窗口的真伪。除了第三方登录还有一个常见的场景是会话过期重新登录。很多 Web 应用会定时弹出会话超时提示并引导用户重新登录。攻击者在页面中伪造一个“会话已过期请重新登录”的弹窗用户输入密码后没有任何异常感因为之前的会话确实经常过期。这是最阴险的一种变体。2.2 凭证捕获后的利用链路攻击者拿到凭证后并不会立即登录。更常见的做法是先用自动化脚本验证凭证是否有效然后延迟数小时甚至数天再登录绕开“异常登录”的实时风控。之后攻击者会利用账号发起重置密码操作检索账号关联的邮箱、手机号甚至尝试在已登录会话中找回支付凭证或身份信息。因此防御不能只盯住“用户是否输入了密码”这个瞬间。真正有效的防护是让凭证即使被捕获也“不能用”。怎么做到短期看是强制的、连续的二次验证如通行密钥、安全密钥长期看则是减少依赖密码的认证体系。后面我会展开。3. 防御体系建设从终端到服务的纵深对抗3.1 用户侧识别三条速判方法十秒分辨真假窗口先说最简单也最能被普通用户接受的训练肉眼。面对一个疑似 BiB 的窗口教你三招第一招尝试拖拽窗口边缘。真实浏览器弹窗的边框可以被拖动来调整大小而且拖动时鼠标指针会切换为调整尺寸的样式。伪造窗口的边框通常是静止的拖动不会产生任何反应。第二招在地址栏输入一段随机字符串再回删。真实浏览器的地址栏支持用户输入而伪造的地址栏通常是只读的。如果你在“地址栏”里输入文字时发现光标根本不出现那这个窗口百分之百是假的。第三招查看新窗口的“新建标签页”按钮是否可用。真实浏览器窗口顶部通常有关闭按钮和新建标签页按钮伪造窗口里这些控件是死的点击没有任何反应。这三招不需要任何技术门槛但前提是用户被提醒过。这也是为什么企业安全意识培训里一定要加入 BiB 攻击的实操演示样本让员工亲眼见过一次“假窗口长什么样”比讲一百页 PPT 有用得多。3.2 Web 开发者侧让你的站点无法成为 BiB 攻击的画布作为 Web 开发者和安全运维你可以从源头上增加攻击者的仿冒成本并把攻击面从用户眼中挤压到代码层面。以下几个措施都经过实测验证有效。启用X-Frame-Options: DENY或frame-ancestorsCSP 指令这是最基础的一步。BiB 的伪造窗口通常需要在一个受控页面中嵌入目标内容或加载目标资源如果你能禁止任何第三方页面嵌入你的页面就封死了一条重要的攻击路径。注意 CSP 的frame-ancestors更灵活可以指定只允许哪些源加载你同时也能影响window.open弹出的窗口虽然不完全限制但增加了攻击者的实现难度。在转账、改密、新增设备绑定等高危操作中引入独立验证界面不要依赖主页面内的任何弹窗而是强制跳转到独立域名或独立路径并在跳转前后要求用户重新确认会话。假如主页面已经被控制攻击者精心伪造的“内部弹窗”将会失效因为你的页面压根不会出现弹窗。使用 FIDO2/WebAuthn 替代密码这是我认为唯一从根上解决问题的技术路径。BiB 攻击的核心目标是骗取密码而 WebAuthn 使用公钥加密和本地设备绑定凭证不会在网络中传输。即使攻击者在伪造弹窗里诱导用户点击“允许”没有用户手指在本机验证器上的触碰确认登录同样无法完成。尽管用户在伪造弹窗里一通操作服务器侧发起的认证挑战携带的是攻击者无法伪造的断言。拥抱通行密钥是目前防御钓鱼最实用的一招。严格管控页面的window.open行为如果你的业务必须使用window.open请把打开的窗口指定固定尺寸、固定位置并且不要让弹窗内容接受外部传入参数来渲染登录表单。更重要的是把第三方登录流程集成进同一页面或使用系统级 OAuth 弹窗而不只是自己画一个“仿系统登录框”。3.3 企业防御策略从单点防御到多因子对抗不管用户是否能够识别企业侧必须默认用户“一定会被迷惑”。比如我们公司内部账号系统在调研后做了一个决定所有核心应用登录页面不再提供弹窗形态而是清一色整页跳转。并且在敏感页面统一叠加一次性口令OTP验证这就是典型的纵深防御——就算凭证泄露攻击者最多拿到第一重因子没有动态口令和设备绑定进来后也无法进行任何破坏性操作。同时推荐部署带有页面语法分析和视觉指纹匹配能力的浏览器安全插件。这类插件会在用户访问目标页面时自动比对页面中的div层级是否出现了“模拟地址栏模拟关闭按钮隐藏域名”的特征。一些成熟的端点安全软件已经内置了这类特征检测规则。我测试过一个结合 Heuristic 规则的方案它能识别出页面中是否有绝对定位元素覆盖了某个注册的敏感选择器比如 Facebook 的登录框并弹出一句警告“当前页面疑似存在嵌入式钓鱼窗口”。虽然识别率做不到百分百但足以在攻击者完成引导之前打断用户操作。最后推荐企业建立内部账号的异常登录基线模型。把“登录时用户是否曾与某个高仿页面发生过交互”“账号在短时间内是否有多个 IP 登录”“登录后的行为是否和历史轨迹一致”作为风控输入。这类模型不用特别复杂的算法规则加权就能拦截大多数 BiB 利用链。4. 检测、发现与应急响应无法避免被钓鱼时怎么办4.1 如何从日志和流量中识别已发生的 BiB 攻击很多时候攻击已经发生但我们并不知道。如果企业自身的某台电脑上用户中了 BiB安全设备会看到以下异常之一DNS 请求中出现了未备案的高仿域名域名主体可能是facebook、login、verify-token等关键词的高相似变体终端的浏览器进程网络连接中出现了向与页面原始域名完全无关的 IP 发送的 POST 请求且请求体里包含表单字段名和密码值页面中出现了光标的异常事件跳转用户在一个页面内操作了超过平时比例的键盘输入事件但很少触发鼠标点击事件因为伪窗口掩盖了真实输入框。建议在 Web 应用防火墙和终端检测响应EDR里同时建立两条规则一条是监测页面对敏感选择器input[typepassword]的加载次数和事件绑定次数另一条是记录每个页面首次用户交互后是否出现对窗口原生对象window.outerWidth、window.screen等的异常调用。BiB 脚本要适配不同分辨率必然去读取这些对象而正常业务页面很少在用户输入密码时反复读取屏幕参数。通过相关系数判断是否中招通常能误报控制在可接受范围内。4.2 已确认被钓后的一小时响应清单假定你确认一个账号刚刚在 BiB 攻击中提交了密码。别慌按照下面顺序操作尽量把损失锁在最小范围。强制吊销所有活跃会话。不要只改密码有些攻击者已经在被钓后的十几分钟内拿到了会话 cookie改密码不会立刻让旧会话失效。必须从后台一次性注销所有设备会话。撤销 OAuth 授权令牌。如果被钓的是第三方登录账号立即从账号安全设置中撤销针对所有应用和站点的授权让攻击者在任何被授权的应用里都无法继续使用旧令牌。检查密码重置链路。攻击者在拿到主账号后通常会立刻修改辅助邮箱和手机号。进入安全设置查看绑定的联系方式是否被改动如果已有未授权的改动先要联系客服申诉恢复控制权。排查关联账号。多数人所有平台都使用同一密码。被钓的账号只是一个入口攻击者会用密码喷洒引擎在几十个主流平台间尝试相同凭证。针对这些平台的逐一强制改密并开启多因素认证操作量很大但不要省略。封存现场并保留证据。保留被钓窗口的截图、浏览器控制台输出以及网络请求的 HAR 记录。这些是后续溯源和追溯攻击者基础设施的关键材料。5. 工具与配置参考部署一套实用的 BiB 防御组合以下工具和配置均基于我在多个环境中的实测无需透露具体厂商只讲思路和关键参数。5.1 浏览器策略强制配置使用企业浏览器或通过组策略管理的 Chrome/Edge可以强行下发以下设置项启用Block third-party cookies阻止第三方 Cookie减少跨域跟踪和凭据传递面启用SameSiteLax或Strict策略要求站点开发者配合设置响应头禁止浏览器自动填充密码到非 HTTPS 页面HTTP 页面全部阻断自动保存标记InternallyManagedAuthenticatorEnabled为企业托管启用设备绑定的通行密钥不允许软令牌导出。另外在浏览器信任视图中禁用“小型弹出窗口中的地址栏隐藏”功能。这一项在部分浏览器中默认开启例如地址栏会随着滚动消失的 PWA 窗口模式。建议将高敏感应用全部以独立标签页打开不用 PWA 模式。5.2 安全 SDK 与反钓鱼引擎集成对自研 Web 应用引入一个轻量级的反钓鱼 JS SDK。SDK 的主要能力不需要包很大只要做到两点扫描页面 DOM检测是否有position: fixed; top:0; left:0; width:100%; height:100%的覆盖层并且覆盖层内包含完整的“浏览器边框元素”。拦截主线程中对window.location的赋值在beforeunload或Virtual DOM层如果即将出现的“新页面”没有经过原生的window.open则判定为异常。SDK 触发警告时不必直接阻断用户操作而是弹出确认框要求用户输入一段随机验证码。真实弹窗不会要求这东西只有伪造弹窗会卡住。这个方法简单粗暴但实测能有效拦截将近八成的 BiB 尝试。5.3 用户培训与红队演练任何技术手段都绕不开最终操作者。每季度做一次“内部钓鱼BiB 混合演练”很有必要。我建议把演练题目设计成“在某个业务系统页面内弹出一个自动续费登录窗口要求你重新输入账号密码”然后统计输入率。第一轮往往超过 50%经过培训和模拟演示后第二轮通常会降到 10% 以下。还要专门给开发团队做一次攻防对抗工作坊让开发人员体验被个仿冒弹窗钓走账号的感觉。事实证明当过受害者之后开发人员在写代码时会不自觉地考虑拒绝弹窗模式、刻意避免在页面内做模拟浏览器 UI这是最划算的防御投入。6. 常见问题与踩坑记录6.1 常见问题速查问题现象可能原因防御与响应建议在合法域名内出现新窗口要求登录页面已被注入 BiB 脚本关闭该标签页从浏览器地址栏手动输入域名访问禁止点击原页面任何元素地址栏无法输入文字或下拉列表空白伪造地址栏被 locked 或被 div 遮挡按住 Ctrl 同时按 L试图切换到真实地址栏输入若仍无法操作直接关闭标签页企业账号未输入密码却收到异地登录告警攻击者利用了已泄露的旧密码启用 MFA、更换密码、收回全部会话并检查是否有设备注册行为部署了X-Frame-Options仍收到 BiB 告警X-Frame-Options只针对 iframe 嵌入但 BiB 可能用功能性弹窗改用 CSPframe-ancestors并增加“不允许脚本创建全屏覆盖层”的 CSPsandbox策略安全软件提示“页面存在伪装窗口”但业务确认是合法登录第三方登录 SDK 为了统一风格隐藏了地址栏升级 SDK 到使用系统级弹窗或把登录页面改为独立整页6.2 踩坑记录那些我以为有效但实际失效的防御措施第一个坑是只依赖账号多因子认证MFA。BiB 傀儡页能实时转发请求或者直接让受害者在这个假窗口输入动态验证码然后攻击者立刻把验证码填入自己正在登录的真会话中这就是我们说的“中间人型钓鱼”。所以推出 MFA 不代表万事大吉有条件务必使用 WebAuthn 通行密钥它绑定设备无法被截获转发。第二个坑是因为 BiB 的存在就把所有弹窗一律封禁。这在部署中会引发业务大量投诉而且无法真正防御攻击因为攻击者可以把伪造弹窗改成position: fixed的抽屉式界面照样能模拟一个“窗口”。核心还是让用户明白任何弹窗内的登录请求都应该先退出弹窗回到浏览器地址栏手动输入并完成两因素验证。第三个坑是以为沙箱化容器能解决一切。远程浏览器如云桌面确实能让恶意代码难以接触凭证但 BiB 攻击的物理目标仍然是用户在屏幕前看到的内容以及用户的输入行为。攻击者可以在云端浏览器页面继续渲染一个假窗口用户照样会输入。沙箱化降低的是“凭证被本地窃取”的风险对于“凭证被用户个人主动提交”的事实几乎无能为力。写在最后我的体会BiB 攻击给整个安全行业提了个醒我们一直在修补浏览器漏洞却忽略了用户早就把“浏览器窗口”的视觉外观当成了安全标识。当你把所有安全提示都建立在地址栏、锁形图标这些可被 CSS 复刻的元素上时就等于把安全的最后一道门交给了攻击者也能精通的“前端技能”。我个人在实际项目里最推荐的方案不是某一个工具而是“用户教育 WebAuthn 全页面跳转”的三合一组合。这套组合在模拟攻击中的拦截成功率能达到 95% 以上而传统依赖 MFA 和易识别域名的组合拦截率不足六成。另外永远不要低估攻击者对业务逻辑的理解水平。BiB 只是皮毛本质上攻的是一个组织的信任共识。最后再分享一个小技巧给你的核心业务页面加一个只有你自己知道的“启动密语”比如在登录按钮上悬停三秒会出现一个隐藏的验证图形。你的用户群经过培训后都知道要等待这个图形出现才能输入密码。攻击者就算仿冒了整个窗口也不会知道这个内部约定。这招不是标准技术但对付量产化的钓鱼模板往往比装一套昂贵系统还管用。