category
你为什么要关心隔离你的网络资源?
许多web应用程序容易受到跨来源攻击,如跨站点请求伪造(CSRF)、跨站点脚本包含(XSSI)、定时攻击、跨来源信息泄露或推测执行侧通道(Spectre)攻击。
Fetch Metadata请求头允许您部署一种强大的深度防御机制——资源隔离策略——以保护您的应用程序免受这些常见的跨源攻击。
由给定的web应用程序公开的资源通常只由应用程序本身加载,而不由其他网站加载。在这种情况下,部署基于Fetch Metadata请求头的资源隔离策略几乎不需要付出什么努力,同时可以保护应用程序免受跨站点攻击。
浏览器兼容性
所有现代浏览器引擎都支持获取元数据请求标头。
浏览器支持
背景
许多跨站点攻击都是可能的,因为默认情况下web是打开的,并且您的应用程序服务器无法轻松保护自己免受来自外部应用程序的通信的影响。典型的跨来源攻击是跨站点请求伪造(CSRF),攻击者引诱用户到他们控制的站点,然后向用户登录的服务器提交表格。由于服务器无法判断请求是否来自另一个域(跨站点),并且浏览器会自动将cookie附加到跨站点请求,因此服务器将代表用户执行攻击者请求的操作。
其他跨站点攻击,如跨站点脚本包含(XSSI)或跨来源信息泄露,本质上与CSRF相似,依赖于从攻击者控制的文档中的受害者应用程序加载资源并泄露有关受害者应用程序的信息。由于应用程序无法轻松区分可信请求和不可信请求,因此无法丢弃恶意跨站点流量。
除了如上所述的对资源的攻击外,窗口引用还可能导致跨源信息泄露和Spectre攻击。您可以通过将跨来源Opener策略响应标头设置为相同来源来防止它们。
Fetch元数据简介
获取元数据请求头是一种新的web平台安全功能,旨在帮助服务器抵御跨源攻击。通过在一组Sec-Fetch-*标头中提供有关HTTP请求上下文的信息,它们允许响应服务器在处理请求之前应用安全策略。这使开发人员可以根据请求的发出方式和使用上下文来决定是接受还是拒绝请求,从而可以只响应自己的应用程序发出的合法请求。
同源
来自您自己的服务器(同源)提供服务的站点的请求将继续工作https://site.example对于资源https://site.example/foo.json在JavaScript中,会导致浏览器发送HTTP请求标头“Sec Fetch Site:same origin”。
跨站点
恶意的跨站点请求可能会被服务器拒绝,因为Sec-Fetch-*标头提供的HTTP请求中有额外的上下文。上的图像https://evil.example已将img元素的src属性设置为'https://site.example/foo.json'导致浏览器发送HTTP请求标头“Sec Fetch Site:cross-Site”。
Sec-Fetch-Site
浏览器支持
Sec-Fetch-Site告诉服务器哪个站点发送了请求。浏览器将此值设置为以下值之一:
相同的来源,如果请求是由您自己的应用程序提出的(例如site.example)
相同的网站,如果请求是由您网站的子域(例如bar.site.example)提出的
无,如果请求是由用户与用户代理的交互(例如点击书签)明确引起的
跨站点,如果请求是由另一个网站发送的(例如邪恶。示例)
Sec-Fetch-Mode
浏览器支持
Sec Fetch Mode表示请求的模式。这大致对应于请求的类型,并允许您区分资源加载和导航请求。例如,navigation的目的地表示顶级导航请求,而无cors表示加载图像等资源请求。
Sec Fetch Dest
Sec-Fetch-Dest公开请求的目的地(例如,如果脚本或img标记导致浏览器请求资源)。
如何使用Fetch元数据来抵御跨源攻击
这些请求头提供的额外信息非常简单,但额外的上下文允许您在服务器端构建强大的安全逻辑,也称为资源隔离策略,只需几行代码。
实施资源隔离策略
资源隔离策略可防止外部网站请求您的资源。阻止此类流量可以缓解常见的跨站点web漏洞,如CSRF、XSSI、定时攻击和跨来源信息泄露。可以为应用程序的所有端点启用此策略,并允许来自您自己的应用程序的全部资源请求以及直接导航(通过HTTP GET请求)。应该在跨站点上下文中加载的端点(例如,使用CORS加载的端点)可以从该逻辑中选择出来。
步骤1:允许来自不发送获取元数据的浏览器的请求
由于并非所有浏览器都支持Fetch Metadata,因此您需要通过检查是否存在Sec Fetch站点来允许不设置Sec Fetch-*标头的请求。
注意:以下所有示例都是Python代码。
if not req['sec-fetch-site']:
return True # Allow this request
步骤2:允许相同网站和浏览器启动的请求
任何非源于跨源上下文的请求(如邪恶示例)都将被允许。特别是以下要求:
- 源于您自己的应用程序(例如,始终允许site.example请求site.example/foo.json的相同源请求)。
- 源自您的子域。
- 是由用户与用户代理的交互(例如直接导航或单击书签等)明确引起的。
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
return True # Allow this request
如果您的子域不完全受信任,您可以通过删除相同的站点值来阻止子域的请求,从而使策略更加严格。
步骤3:允许简单的顶级导航和iframe
为了确保您的网站仍然可以从其他网站链接,您必须允许简单的(HTTPGET)顶级导航。
if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
# <object> and <embed> send navigation requests, which we disallow.
and req['sec-fetch-dest'] not in ('object', 'embed'):
return True # Allow this request
上面的逻辑保护您的应用程序的端点不被其他网站用作资源,但将允许顶级导航和嵌入(例如在<iframe>中加载)。为了进一步提高安全性,可以使用Fetch Metadata标头将跨站点导航限制为仅允许的一组页面。
步骤4:选择退出旨在服务于跨站点流量的端点(可选)
在某些情况下,您的应用程序可能会提供跨站点加载的资源。这些资源需要在每个路径或每个端点的基础上豁免。此类端点的示例有:
- 要跨原点访问的端点:如果您的应用程序正在为启用CORS的端点提供服务,则需要明确地将它们从资源隔离中选择出来,以确保对这些端点的跨站点请求仍然是可能的。
- 公共资源(如图片、样式等):任何应可从其他网站跨来源加载的公共和未经验证的资源也可以豁免。
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
return True
注意:在从这些安全限制中选择退出部分应用程序之前,请确保它们是静态的,并且不包含任何敏感的用户信息。
步骤5:拒绝所有其他跨站点且不可导航的请求
此资源隔离策略将拒绝任何其他跨站点请求,从而保护您的应用程序免受常见的跨站点攻击。
默认情况下,违反策略的请求应被HTTP 403响应拒绝。但是,根据您的用例,您还可以考虑其他操作,例如:-仅记录违规行为。这在测试策略的兼容性并查找可能需要选择退出的端点时尤其有用。-正在修改请求。在某些情况下,请考虑执行其他操作,如重定向到您的登录页和丢弃身份验证凭据(如cookie)。但是,请注意,这可能会削弱基于获取元数据的策略的保护。
示例:以下代码演示了在服务器上或作为中间件来拒绝潜在恶意跨站点资源请求的强大资源隔离策略的完整实现,同时允许简单的导航请求:
# Reject cross-origin requests to protect from CSRF, XSSI, and other bugs
def allow_request(req):
# Allow requests from browsers which don't send Fetch Metadata
if not req['sec-fetch-site']:
return True
# Allow same-site and browser-initiated requests
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
return True
# Allow simple top-level navigations except <object> and <embed>
if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
and req['sec-fetch-dest'] not in ('object', 'embed'):
return True
# [OPTIONAL] Exempt paths/endpoints meant to be served cross-origin.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
return True
# Reject all other requests that are cross-site and not navigational
return False
部署资源隔离策略
- 安装一个模块,如上面的代码片段,以记录和监控您的网站的行为,并确保这些限制不会影响任何合法流量。
- 通过豁免合法的跨原点端点来修复潜在的违规行为。
- 通过删除不符合要求的请求来强制执行策略。
识别和修复违反策略的行为
建议您先在服务器端代码中以报告模式启用策略,以无副作用的方式测试策略。或者,您可以在中间件中或反向代理中实现此逻辑,反向代理记录您的策略在应用于生产流量时可能产生的任何违规行为。
根据我们在谷歌推出获取元数据资源隔离策略的经验,大多数应用程序默认情况下都与此类策略兼容,并且很少需要豁免端点来允许跨站点流量。
强制执行资源隔离策略
在您检查了您的策略不会影响合法的生产流量后,您就可以实施限制,确保其他网站无法请求您的资源,并保护您的用户免受跨网站攻击。
注意:在运行身份验证检查或对请求进行任何其他处理之前,请确保拒绝无效请求,以防止泄露敏感的时间信息。
进一步阅读
- W3C Fetch Metadata Request Headers specification
- Fetch Metadata Playground
- Google I/O talk: Securing Web Apps with Modern Platform Features (Slides)
Was this helpful?
- 登录 发表评论