关于CSRF攻击与Access-control-allow-origin配置安全性的探讨
CSRF定义
CSRF全称Cross-site request forgery,中文作“跨站请求伪造”
是一种挟持用户在当前已登录的Web网站上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,而CSRF 利用的是网站对用户(浏览器)的信任。
攻击流程
用户Client访问并登录可信站点A,浏览器获取并记录Cookie,在Cookie未失效时打开含有恶意代码的站点B,此时站点B中包含的恶意代码在用户有可能不知情的情况下,以用户身份执行某些操作,例如在站点A中执行转账操作。
跨域配置
Access-control-allow-origin头一般来说仅在需要时进行配置,意在允许指定域名跨域访问或调用本站资源,一般分两种情况:
情况一:
一般应用在开源公共库中:允许任意用户调用开源公共库中的js、字体等文件
此时开源公共库的Access-control-allow-origin应配置为*,即允许所有域名跨域访问或调用本站资源
情况二:
站点动静分离,js、css等文件使用CDN技术实现加速,加速域名与原站点域名不一致,即跨域访问
此时应配置静态资源所在的CDN节点的Access-control-allow-origin为主站域名,即允许主站跨域调用CDN节点资源
安全性分析
根据万维网联盟w3c网站关于Cross-Origin Resource Sharing推荐标准(截止2019年11月20日最新修订本为20140116版)第6.1中所述:
其中第3条详细介绍了如果资源涉及凭证,除了增加“Access-control-allow-origin”标头Origin外还需要添加“Access-Control-Allow-Credentials”标头为“true”,也可以只设置“Access-control-allow-origin”标头Origin或“*”。
同时在注意中使用绿色文本标记了“The string "*" cannot be used for a resource that supports credentials.”,即字符串“*”不能用于涉及凭证的资源
也就是说,其实即便将“Access-control-allow-origin”标头设置为“*”,是否真正存在安全风险主要还是要看浏览器对w3c推荐标准的落地执行程度如何,如果严格执行w3c推荐标准,同时站点代码设计合规,理论上是可以防止CSRF发生的。
截止本文本次更新,万维网联盟w3c网站已经更新了关于Cross-Origin Resource Sharing推荐标准(标准更新日期为:2022年3月17日),在“通过 IP 身份验证或防火墙保护数据的资源”使用Access-Control-Allow-Origin: *时定义为不安全的,其他情况均已视为安全,其中“防火墙保护数据的资源”是指网站程序与用户之间存在防火墙或WAF,且网站程序无法获得用户的真实访问信息的情况。综上所述,在网站程序设计和配置上均合规的情况下,设置“Access-control-allow-origin”标头设置为“*”已不会导致CSRF情况。