浏览器中xhr选项是做什么用的呢_如何绕过Play框架中的CSRF保护(CVE202012480漏洞)...

0d2281b689cb60fd4e750c61d25a1bd8.gif

我会在这篇文章介绍一个影响Play框架的漏洞,此漏洞允许在特定配置下绕过完整的跨站点请求伪造(CSRF)保护。play 框架是一个full-stack(全栈的)Java Web的应用框架,包括一个简单的无状态MVC模型,具有Hibernate的对象持续,一个基于Groovy的模板引擎,以及建立一个现代Web应用所需的所有东西。

不过在攻击者眼中,Play框架是一个针对java和scala的高速web框架。它构建在Akka之上,Akka是一个工具包,用于为Java和Scala构建高度并发、分布式和弹性的消息驱动应用程序。

Play是一种广泛使用的框架,并且已部署到大型和小型组织的Web平台上,例如Verizon,Walmart,The Guardian,LinkedIn,Samsung等。

69a83f4eda37ef3f83fe107538003467.png

较早版本的反csrf机制

在较早版本的框架中,CSRF保护是由一种不安全的基线机制提供的,即使在HTTP请求中没有出现CSRF令牌时也是如此。

这种机制基于简单请求和完整请求之间的基本区别,简单请求具有严格的规则集,只要遵循这些规则,即使通过XMLHttpRequest,用户代理(例如浏览器)也不会发出OPTIONS请求。尽管我们主要对Content-Type规则集感兴趣,但可以在此Mozilla的开发人员页面上看到所有规则和详细信息。

简单请求的Content-Type标头可以包含以下三个值的一个:

d3f9c37c49b19d3d4627ee399c0c3d35.png

如果你指定了不同的内容类型,比如application/json,那么浏览器将发送一个选项请求来验证web服务器是否允许这样的请求。

现在我们了解了完整请求和简单请求之间的区别,可以继续了解Play是如何抵御CSRF攻击的。

在该框架的旧版本中(包括2.5版本之前),在接收内容类型报头时使用黑名单方法作为CSRF预防机制。

在2.8.x迁移指南中,我们可以看到用户如何根据旧版系统或其他依赖项的要求恢复Play的原有默认行为:

69a83f4eda37ef3f83fe107538003467.png

application.conf

ac506ad798e8d1994b1d7d9b942a5e0e.png

在上面的代码片段中,我们可以看到原有保护的核心。contentType.blackList设置包含三个值,它们与“simple requests”的内容类型相同。由于防止了以下情况,因此已将其视为有效的(尽管不是理想的)保护:

1.Attacker.com嵌入

2.Attacker.com使用XHR通过application / json将其发布到victim.com,由于application / json不是一个“simple request”,因此将发送一个OPTIONS,并且CORS将阻止该请求(假设配置正确)。

3. victim.com使用XHR将application / json发布到victim.com,由于请求不是跨站点的,而是在同一个域内,因此它应能正常工作。

以上就是CSRF保护的机制。

69a83f4eda37ef3f83fe107538003467.png

如何绕过

有了以上这些知识铺垫,首先想到的就是我们需要使浏览器发出一个不会触发预检并且与contentType.blackList设置中的任何值都不匹配的请求。

我们要做的第一件事是绘制出可以在不发送OPTIONS预检的情况下进行修改的请求,这还可以归结为一个请求:Content-Type:multipart / form-data。

使用边界值Content-Type: multipart/form-data; boundary=something,会立即显得很有趣。详细描述可以在这里找到:

c2d03a1948b1f05435237e486bfba9fc.png

因此,我们有一个字段,实际上可以修改与许多不同的字符,它是所有攻击控制。

现在我们需要深入分析这些头,为了做到这一点,我们需要看一下Play框架所基于的Akka HTTP。

查看HttpHeaderParser.scala,我们可以看到这些标头始终是被解析的:

b3d0123b23a194a27d9ec216c49232c4.png

解析规则可以在HeaderParser.scala中看到,该文件遵循RFC 7230超文本传输协议(HTTP / 1.1):消息语法和路由,2014年6月。

bea6a798e738d0ee22ea6451837d7e82.png

如果不遵守这些解析规则,则该值将设置为None。完美!这正是我们绕过CSRF保护所需要的一个“简单请求”,然后将其设置为None,从而绕过黑名单。

我们如何伪造一个被浏览器允许,但Akka HTTP解析代码认为无效的请求呢?

于是我们决定模糊化这个请求,并很快发现下面的转换是有效的:

Content-Type: multipart/form-data; boundary=—some;randomboundaryvalue

在边界值内加一个分号就可以了,它会把请求标记为非法:

707a530c499c837909577487e22d6f66.png

69a83f4eda37ef3f83fe107538003467.png

响应

a5509811680cbc70f198a6086bb82ec9.png

通过在开发模式下查看服务器的日志也可以确认这一点:

cafdd183340c8c46e72049f0c0a45955.png

并且通过检测Play框架代码来打印Content-Type的值:

Content-Type: None

最后,我们构建了以下概念验证并通知了Play框架维护人员:

2182896927452ac980c1fe5a97fd89da.png

此漏洞已在Play 2.8.2和2.7.5中修复,且在2020年8月10日被命名为CVE-2020-12480 。

参考及来源:https://blog.doyensec.com/2020/08/20/playframework-csrf-bypass.html

4d602d3064c48592daee21d34d71e2ff.png

3cc286a7f2667d6f05abe8d6d6bb0efe.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值