Referer头和Web安全

Referer 是一个常见的请求头,在跳链或者发送请求时附带该头字段,可以让服务器识别请求发起的页面地址,以确定如何对请求进行响应,通常来说它有以下两个应用场景。

防止CSRF攻击

正常情况下,用户U在银行站点B完成转账,此过程中U的所有操作均发生在B的站点上,发送的请求携带B的Cookie。
现有一个攻击者站点A,用户U被诱导点进来之后A会自动向银行网站B发送转账请求(这里也可以携带B的Cookie),那么如果B网站没有做安全处理,转账请求可能就起作用了,结果用户U平白无故损失了一笔钱。
以上是一个简单的 CSRF 攻击场景,可见B站点需要补充一些安全措施来防御这种攻击。增加Referer头字段校验是其中一种方法,Referer 是浏览器自动添加的头字段,值一般是发送请求页面的origin(协议+域名),该字段无法人工添加和修改,B站点服务器可以通过检验该字段是否在配置的白名单之内,来限制那些伪造的请求。在本例中假设B的域名为www.money.com,则从Referer头中提取出字符串,解析为URL格式,匹配域名部分是否相等即可。
那么这样做了之后,是不是就绝对安全呢?其实也不见得,问题就出在上句中标粗字体那里。随着业务的发展,B站点会把一些子域名、其他业务线的域名也纷纷加入白名单,然后有一天一位技术人员觉得白名单太长成了流水账,于是他把校验方式改成了正则校验/www\.money\.com/.test(referer),看上去白名单结构清晰多了,但却引入了意想不到的安全漏洞。
攻击者C某天浏览站点时发现转账的安全校验竟然如此简单,既没有token,也没有验证码,只通过一层Referer进行了限制。”窗户纸一捅就破!”C潜心研究了几个小时,发现链接http://c_site/www.money.com/a/b/c竟然可以成功绕过Referer校验!是的,因为这个链接可以成功通过正则匹配,也就为C实施接下来的一系列恶意操作提供了便利。
你可能觉得上面的例子太简单,但这是根据一个真实的案例改编来的,IBM的邮箱系统都会出现这样的问题,安全无小事,还是要时刻注意提防。

统计用户特征

Referer头不仅可以携带请求方的origin,还可以通过修改配置让它携带完整的URL链接,这就为埋点统计提供了方便。比方说用户在https://www.money.com/a/b/c?query=d的链接发送一个请求,Referer字段的值就是这个链接,后端服务器可以拿到该字段进行分析,来统计某个功能在特定页面使用的频次。
这种携带完整链接作为Referer的方式看似没啥问题,但这既方便了你,同时也方便了别人。那谁是“别人”呢?比如说你的站点被cdn攻击恶意植入了一个a标签,当用户点击这个标签之后,攻击者就可以通过Referer头字段推测出你站点的层级结构,更危险的情况是URL上携带有token等身份信息时,攻击者就可以盗取用户token进行攻击。另一种更糟糕情况是你的站点还存在Redirect导致的SSRF漏洞,攻击者盗取链接后可以进行分析并最终绕过安全认证,你的整个站点系统对他来说就一览无余了。
所以说Referer头携带完整URL链接也是不安全的,一直以来我都不建议在项目中这么去用,如果真的是要统计埋点数据的话,在前端构造请求即可。
上面提到a标签可能泄露你的站点链接,所以项目中包含跨域链接时最好做一些处理,如<a href="http://example.com" referrerpolicy="origin"><a href="http://example.com" rel="noreferrer">,这两种方法都限制了Referer头部的发送,你也可以直接添加meta标签全局设置Referer发送策略<meta name="referrer" content="origin">
上面提到的Referer控制机制叫做Referrer Policy,浏览器提供了很多选项来控制请求中是否发送Referer头部,然后是发送origin还是完整链接,下面是几个常见的选项:

项目含义
no-referrer始终不携带Referer头部
origin始终发送origin信息作为Referer
no-referrer-when-downgrade请求同协议的链接始终携带完整url,否则不发送(不推荐)
same-origin相同源站点发请求时携带完整url,否则发送origin

完整的选项和示例介绍可以看这里

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Web应用中,可以通过服务器端来校验请求的Referer字段。下面是一些常见的校验Referer的方法: 1. 后端校验:在服务器端接收到请求后,可以通过获取请求中的Referer字段值来进行校验。 - 对于基于Java的应用程序,可以使用HttpServletRequest对象获取Referer字段的值,例如:`String referer = request.getHeader("Referer");`。 - 对于其他后端语言和框架,也有相应的方式来获取请求中的Referer字段值。 2. 验证合法来源:根据您的业务需求和安全策略,对Referer字段的值进行验证,以判断请求是否来自合法的来源。 - 验证域名:比较Referer字段中的域名与您应用程序的域名是否匹配,可以使用字符串匹配或正则表达式进行比较。 - 验证协议和端口:除了验证域名外,还可以验证Referer字段中的协议(如httphttps)和端口号是否与您的应用程序要求一致。 - 白名单验证:维护一个白名单,包含您信任的Referer来源。对于每个请求,检查Referer字段的值是否在白名单中。 3. 处理未通过验证的请求:如果验证失败,即Referer字段的值不是您预期的合法来源,您可以采取适当的措施,如拒绝请求、重定向到错误页面、返回错误状态码或记录异常日志。 请注意,校验Referer字段并不是绝对可靠的安全措施,因为Referer值可以被伪造或篡改。因此,建议结合其他安全措施,如使用CSRF令牌、同源检测等来提高应用程序的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值