通过Server Push和SXG实现跨源web攻击的学习
前言
本文来自清华大学的一项研究
为了避免做重复机械的翻译工作,我会同时从一个水平一般的学习者的角度讲解我学到的东西,如有不当之处,务必指正
SOP是什么
SOP全称same-origin policy,翻译成中文就是同源策略
SOP是web安全的基石,它被设计用于防护跨源攻击
那么什么是同源什么是跨源呢,要弄清这个问题,我们需要先知道源的定义:由协议、主机名、端口号三者确定的三元组,(e.g. {“https”,”a.com”,”443”})只有这三部分完全相同时才叫做同源,很显然他是基于URI的(URI-based)
图中的a.com和b.com显然为不同源的两个站点,SOP就像一个隔板,将这两个网站隔开,如果用户通过浏览器从a.com向b.com的服务器发送请求,同源策略会拦截b服务器返回的数据,比如常见的xss,在跨站攻击的时候可以通过iframe从一个网站引入另一个网站的资源,如果不同源,就会被SOP拦截
SAN是什么
SAN全称是Subject Alternative Name,翻译成中文是使用者备用名称
在TLS/SSL证书中,SAN的作用是解决单证书适配多域名的需求,在早期传统的证书中,存在一个CN字段,用于表示主域名,仅支持单域名,而SAN支持绑定多个域名,并且,除了域名,SAN还支持绑定IP,邮箱,URI

这就是SAN字段可能包含的内容,与之相似的还有一个叫做通配符证书的东西,通配符证书也就是类似于*.example.com
它可以作用所有后缀为.example.com的子域名,显然灵活性远远不如SAN
HTTP/2 和 HTTP/3认为所有在证书的SAN里面的主域名是”同源“的,这里的同源和浏览器SOP认为的同源不完全一样
主要是视这些主机具有同一 TLS 权限
SAN-based origin
显然和前面的URI-based origin相比,基于SAN的同源要求更松,也就意味着它的灵活性更好,96%的证书在SAN列表中有多个域名,甚至3.2%的证书还包含来自不同组织的域名
这种更为激进的“源”会给网络带来什么新的威胁?
在这之前,我们需要了解一些前置知识
HTTP/2 Server Push

传统的没有Push的方式需要浏览器向服务器请求多次来获取所需的所有资源,这回浪费时间,影响用户体验。
而Push就是当用户请求了html之后,服务器就会直接把需要的资源比如css发到浏览器。
那么他是怎么实现的呢
通过Nginx的实现
配置文件conf/conf.d/default.conf
1 | |
关注最后两行的内容,它表明如果用户请求根目录,就会自动push style.css和example.png这两个文件
通过Apache的实现
配置文件httpd.conf或者.htaccess
1 | |
通过后端实现
前面两种是通过代理的配置文件实现,略显繁琐
可以让后端应用返回一个HTTP回应的头信息Link命令,服务器看见这个命令,就会自动Push指定的文件
1 | |
此时,再修改Nginx的配置
1 | |
解决缓存问题
因为浏览器是有缓存的,他会把css等文件缓存到本地,这时再重复推送显然很浪费带宽。Nginx官方提出的一种解决办法是仅当用户第一次访问的时候才Push,根据Cookie来判断用户是否是第一次访问,配置方法如下
1 | |
SXG
SXG全称是Signed HTTP Exchange
借助SXG,发布商可以对单个HTTP交换(即请求/响应对)进行签名,这可让发布商安全地确保内容可移植(即可供其他方重新分发),同时保留内容的完整性和出处。
比如这里,a网站发布了一个内容,b网站作为一个服务商,可以让用户查看这个内容,在用户查看这个内容的时候,浏览器回加载这个Signed Exchange,它可以安全的在地址栏里面显示发布商的网址,也就是a.com。常见的场景是CDN。
如果想要不通过SXG来实现这个功能,则需要不同的网站共享TLS的密钥,这会带来一些安全问题。
共同点
- 他们都遵守SAN-based origin
- 他们都可以通过服务器的响应在共享的证书中表明(欺骗)他们的“源”(通过
:authority伪标头和request-url签名标头)
影响
攻击者可以Push/Provide资源到SAN列表中的其他站点,也就是CrossPush And CrossSXG 攻击
- 获取一个与受害者网站共享的证书
- 引诱用户访问攻击者的网站
- 在攻击者服务器向用户Push内容时,因为与victim.com同在一个SAN列表中,所以他们拥有相同的TLS权限,攻击者可以通过伪造
:authority来指向受害者的网站,攻击者也可以通过篡改 SXG 中的request-url和validity-url头部,虚假标注恶意内容的来源,指向victim.com - 浏览器会接收到攻击者服务器Push的恶意脚本(比如XSS),将其视为来自同源的victim.com网站,并在访问victim.com时执行它
这使得路径外的攻击者借助共享证书发起可以实际落地的web攻击
1 | |
攻击方式
借助HTTP body
通用的XSS
有一篇博客很好的讲解了这个过程: https://tttang.com/archive/1703/
即使有CSP,也无法阻止这样的攻击
操纵Cookie

原理:
在HTTP/2协议中,TLS权限的主体是按照SAN列表来定的,证书里的所有域名都是同一权限,而浏览器的同源策略是按 照URI的域名来判定的,这就导致了差异,如果攻击者服务器与victim.com同在一个SAN列表中,攻击者服务器在设置 domain=victim.com时,HTTP/2会认为这是合法的,从而导致浏览器认为这个设置也是合法的,于是允许了这次Set- Cookie
绕过HSTS
**HSTS:**HTTP Strict Transport Security,即HTTP严格传输安全,也就是强制浏览器仅通过HTTPS与服务器进行通信
利用共享的证书,攻击者可以通过设置max-age=0,并且让浏览器误以为这是victim.com自己发的,从而让HSTS失效
恶意文件下载
攻击者通过设置Conten-Disposition,attachment告诉浏览器这是一个附件,需要下载,同时利用共享的证书,让浏览器信任攻击者的服务器,下载了恶意的木马文件
如何让这些攻击方式落地?
要是实现这些攻击,考虑以下三个问题
- 如何获得与受害者服务器共享的证书
- 如何让攻击持久化
- 如何绕过潜在的对策,比如证书撤销
获得与受害者服务器共享的证书
利用一些缺陷
/.well-known目录中不安全的文件上传
1 | |
域名所有权下未受保护的 _acme-challengeDNS 记录
1 | |
邮件服务商在保护域名的管理邮箱地址时存在疏忽
1 | |
目前没有强制的措施能够保证域名的所有者和证书的所有者身份一致,那么攻击者是完全可以获取到共享的证书的
具体的获取方法
方法一:倒卖域名
攻击者可以申请一张包含多个域名的证书,然后把其中的某个域名卖给受害者
方法二:域名接管
有一些域名可能曾经被注册过,但是过期后没有继续续费,但是他曾经申请的TLS证书还是有效的,如果该域名与一些 重要的域名同在一个SAN列表中,攻击者就可以购买这个域名并对这些重要域名发起攻击
延长攻击持续时间
先介绍一下验证复用机制,在TLS生态中,CA为了简化验证流程,当用户首次通过DNS-01/HTTP-01/邮箱验证之后,CA会缓存这次验证结果,在一段有效期内,如果用户再次申请该域名的证书,无需重复进行验证,之间复用之前的缓存结果即可签发证书。攻击者先购买一个域名,在申请完证书之后就有了缓存,如果这个时候域名过期了,被受害者买去了,攻击者任然可以继续申请证书。
下图为不利用验证复用机制的情况下攻击可以持续的时间,在域名被买走之前攻击者申请了一个证书,攻击可以持续直到证书过期。
而在利用验证复用的情况下,攻击持续时间会大大加长
绕过防御策略
当受害者意识到攻击者获得了共享的证书时,肯定会想办法撤销证书。而这个证书包含了攻击者域名和受害者域名,想要撤销需要满足以下两点要求之一
- 对证书上的所有域名执行并通过DOV认证(DOV:Domain-Validated Only,也就是对域名所有权进行严格的鉴定)
- 拥有私钥
而受害者这两点要求都没办法满足,对于第一点,因为攻击者的域名也在证书上,显然受害者没法对其完成DOV认证;对于第二点,证书是攻击者签发的,私钥在攻击者那里,也没办法满足。
所以受害者无法撤销这样的共享证书
大规模测试
论文中,研究员们利用这个方法分别对客户端和服务端进行了真实的实验,验证了攻击的可行性,这部分省略,感兴趣的师傅可以查看原文
缓解攻击
从浏览器供应商
在浏览器中强制执行一致的authority(IP)以缓解CrossPUSH
强制单域名证书来缓解CrossSXG
从证书认证
在 SAN 列表中的域名所有者提出请求时,协助其将自己的域名从共享证书中移除
从用户
在注册域名时检查证书状态
CTF例题
题目分析
SECCON CTF 14(2025) Quals–broken challenge
这题考察的是xss,只有一个bot,可以让bot访问可控的网站,访问方法如下
1 | |
并且一个特定的自签名证书颁发机构 (cert.crt) 被安装在机器人的环境中,作为“受信任的根证书”。访问/'hint可以获取私钥
1 | |
因为该域名根本不存在,所以没办法进行DNS解析
思路
这题就可以利用前面提到的SXG,我们有了这个站点的证书,就可以利用起来伪造一个由hack.the.planet.seccon网站签发的SXG文件,内容是一个外带cookie的payload,然后让bot访问这个网页,浏览器会认为这个文件的发布者是hack.the.planet.seccon,于是就我们的外带的payload就可以读到cookie并发到我们的vps上,拿到flag
感想
认认真真翻译一篇论文,遇到不懂的就去查,学到了非常多的东西,尽管零零散散的看,前前后后花了四五天,但是还是挺有意义的。