我会在这篇文章介绍一个影响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等。
较早版本的反csrf机制
在较早版本的框架中,CSRF保护是由一种不安全的基线机制提供的,即使在HTTP请求中没有出现CSRF令牌时也是如此。
这种机制基于简单请求和完整请求之间的基本区别,简单请求具有严格的规则集,只要遵循这些规则,即使通过XMLHttpRequest,用户代理(例如浏览器)也不会发出OPTIONS请求。尽管我们主要对Content-Type规则集感兴趣,但可以在此Mozilla的开发人员页面上看到所有规则和详细信息。
简单请求的Content-Type标头可以包含以下三个值的一个:
如果你指定了不同的内容类型,比如application/json,那么浏览器将发送一个选项请求来验证web服务器是否允许这样的请求。
现在我们了解了完整请求和简单请求之间的区别,可以继续了解Play是如何抵御CSRF攻击的。
在该框架的旧版本中(包括2.5版本之前),在接收内容类型报头时使用黑名单方法作为CSRF预防机制。
在2.8.x迁移指南中,我们可以看到用户如何根据旧版系统或其他依赖项的要求恢复Play的原有默认行为:
application.conf
在上面的代码片段中,我们可以看到原有保护的核心。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保护的机制。
如何绕过
有了以上这些知识铺垫,首先想到的就是我们需要使浏览器发出一个不会触发预检并且与contentType.blackList设置中的任何值都不匹配的请求。
我们要做的第一件事是绘制出可以在不发送OPTIONS预检的情况下进行修改的请求,这还可以归结为一个请求:Content-Type:multipart / form-data。
使用边界值Content-Type: multipart/form-data; boundary=something,会立即显得很有趣。详细描述可以在这里找到:
因此,我们有一个字段,实际上可以修改与许多不同的字符,它是所有攻击控制。
现在我们需要深入分析这些头,为了做到这一点,我们需要看一下Play框架所基于的Akka HTTP。
查看HttpHeaderParser.scala,我们可以看到这些标头始终是被解析的:
解析规则可以在HeaderParser.scala中看到,该文件遵循RFC 7230超文本传输协议(HTTP / 1.1):消息语法和路由,2014年6月。
如果不遵守这些解析规则,则该值将设置为None。完美!这正是我们绕过CSRF保护所需要的一个“简单请求”,然后将其设置为None,从而绕过黑名单。
我们如何伪造一个被浏览器允许,但Akka HTTP解析代码认为无效的请求呢?
于是我们决定模糊化这个请求,并很快发现下面的转换是有效的:
Content-Type: multipart/form-data; boundary=—some;randomboundaryvalue
在边界值内加一个分号就可以了,它会把请求标记为非法:
响应
通过在开发模式下查看服务器的日志也可以确认这一点:
并且通过检测Play框架代码来打印Content-Type的值:
Content-Type: None
最后,我们构建了以下概念验证并通知了Play框架维护人员:
此漏洞已在Play 2.8.2和2.7.5中修复,且在2020年8月10日被命名为CVE-2020-12480 。
本文翻译自:https://blog.doyensec.com/2020/08/20/playframework-csrf-bypass.html如若转载,请注明原文地址: