不安全的gRPC实施如何损害API,应用程序
企业正在转向微服务架构来构建面向未来的应用程序。微服务使企业能够有效地管理基础架构,轻松部署更新或改进,并帮助IT团队创新,失败和更快地学习。它还使企业能够设计出可以轻松按需扩展的应用程序。此外,随着企业转换架构(从传统的单片式服务过渡到微服务),出现了在微服务之间进行有效通信的需求。客户端和服务器应用程序之间的这种关键而复杂的通信可以通过gRPC处理,这是一个通用的远程过程调用(RPC)框架,可促进已连接系统之间的透明,高效的通信。尽管它很新(仅由Google在2015年开发),但它很快获得了普及和采用。
在此博客中,我们将讨论开发人员在转向gRPC并在其项目中实现gRPC时可能面临的安全隐患。由于安全的gRPC API在整个应用程序安全中起着至关重要的作用,因此我们提供了有关如何保护gRPC实施免受威胁并减轻风险的建议。
什么是gRPC?
gRPC可用于设计要求准确性,效率和语言独立性的新协议,因为它支持服务器和客户端的多种语言。它是一个云原生计算(CNCF)项目,并已被各大公司采用,例如流行的视频流网站Netflix,金融服务公司Square和平台即服务(PaaS)公司Docker。
将gRPC与其他RPC框架(例如SOAP和REST)进行了比较。尽管RESTful API被广泛使用,并且通常使用HTTP在应用程序或服务与JavaScript Object Notation(JSON)数据格式之间交换信息,但是它们具有性能和基于文本的方向限制。
许多组织已将其API从REST迁移到gRPC,以利用更适合服务间通信的gRPC二进制协议。默认情况下,gRPC使用HTTP / 2(基于二进制的协议)作为底层。HTTP / 2在一个TCP连接中支持多个流和请求,与其之前的HTTP / 1.0不同,HTTP / 1.0被设计为具有“单个请求,单个答复”方案。HTTP流水线解决了HTTP / 1.1中的此问题;但是,HTTP 2.0仍然具有更高的性能和受支持的能力。
图1. HTTP / 1.0与HTTP / 2在请求和答复方面的不同之处的可视化
gRPC建立在协议缓冲区(或protobuf)之上,后者是Google的平台和语言中立机制,用于序列化结构化数据。序列化是将内存中的对象转换为字节流的过程,可以轻松地将其保存到文件中或通过网络传输给其他应用程序。开发人员只描述一次数据接口,然后使用协议缓冲编译器针对所选语言进行编译。对于gRPC,协议缓冲区也用于定义RPC接口。
图2. gRPC框架如何在在线零售应用程序中工作的图示,该产品具有通过API进行交互的产品和支付服务
图3.发送字符串消息的gRPC“ HelloWorld”演示示例
图片来源:gRPC快速入门
gRPC的潜在威胁和风险
漏洞
gRPC支持多种编程语言。支持的语言中使用两种类型的实现:a)使用语言本身的实现,以及b)gRPC C核心书面代码的包装。这些包装器可以将以不同支持的语言编写的调用转换为C调用。尽管C语言实现通常可以很好地执行,但是由于需要实现更多功能以及内存管理功能,因此开发人员将漏洞引入系统的可能性更高。另一方面,使用诸如Java或Go之类的语言,这些语言已经实现了很多功能,并且还考虑了内存管理问题,这降低了开发人员向系统中引入严重影响的bug的机会。值得注意的是
支持的编程语言 | 实际执行 |
C / C ++ | 是 |
C# | 是的* |
镖 | 是 |
走 | 是 |
爪哇 | 是 |
Kotlin / JVM | 是 |
Node.js | 是** |
目标C | 没有 |
的PHP | 没有 |
蟒蛇 | 没有 |
红宝石 | 没有 |
WebJS | 是 |
*可以使用纯C#实现或围绕C的C#包装器
**纯JavaScript实现以及与gRPC C核心的绑定(使用C ++附加组件)
不安全的数据传输通道和通道凭证
在远程过程调用期间,很有可能会将数据传输到目标服务器。这就是为什么开发人员应优先考虑为数据传输设置安全通道。这样做不仅可以防止数据泄漏,而且可以限制中间人(MiTM)攻击,因为熟练的攻击者可能会泄漏服务数据或向连接中注入恶意数据,这将干扰服务器。
数据泄漏可能会泄露有关您的服务或基础结构的实施详细信息,从而可能引发进一步的攻击,甚至导致服务或基础结构受到损害。这是从不安全的gRPC调用捕获数据包的示例:
图4.从不安全的gRPC调用捕获数据包的示例
gRPC支持整个基础HTTP / 2协议上的TLS以及各种身份验证机制。选择安全的实现是开发人员的责任。出于明显的原因,应避免使用诸如“ InsecureChannelCredentials”之类的关键字进行复制和粘贴模式。
我们已经执行Github.com代码搜索“ InsecureChannelCredentials”关键字以及C ++语言限制(这是gRPC使用的常见限制)。搜索产生了超过11,000个代码结果。我们相信大量的搜索事件与演示和示例相关。但是,仍然有一些项目使用它们。
图5.“ InsecureChannelCredentials”代码搜索结果
程序执行问题
同样,对于AWS Lambda函数,最大的漏洞表面隐藏在实际的远程过程实现中。因为gRPC支持多种语言,所以我们建议新手开发人员使用内存安全的语言,以避免产生高影响力的内存管理错误,例如缓冲区溢出或导致远程代码执行(RCE)的免费使用(UaF)错误。
但是,使用内存安全语言仍然无法减轻代码中可能出现的逻辑错误。为此,开发人员应为开发流程设定高标准,始终遵循安全软件开发最佳实践,并通过使用OWASP安全编码实践中的OWASP十大主动控制建议来实施主动控制。
即使在隔离的网络或私有云内部,也强烈建议对系统的关键部分使用集中式身份验证机制。在配置错误的情况下,环境内部的漏洞利用可能充当未授权访问的入口,这可能会严重干扰gRPC服务。
我们还建议不要将gRPC身份验证详细信息硬编码或提交给供应链管理(SCM)系统,尤其是面向公众的系统。像任何其他凭据信息一样,这些凭据信息应存储在安全的位置,并且仅在需要时访问。这是一个gRPC凭证泄漏的示例,我们仅通过在GitHub上进行搜索就发现了它:
图6.在GitHub上找到的gRPC服务凭证示例
拒绝服务攻击
最后,我们想讨论我们的拒绝服务(DoS)攻击发现。gRPC可以充当隔离环境中的“隐藏”消息服务,以及使用JSON格式的API替代面向公众的REST API服务。
我们想警告C / C ++ gRPC用户一个已知的但仍未修复的错误,该错误会在服务重新启动之前有效地拒绝服务调用。在短时间内打开大量连接时会触发该错误。实际上,这是由于Linux系统上打开的文件描述符的数量受到限制。
图7. gRPC库的C / C ++实现内部的DoS攻击示例
根据我们的研究,在短时间内打开套接字连接,甚至在关闭打开的套接字后,也会触发该错误。我们用Java和Go等非C语言包装的其他语言测试了此实现,发现它们不受此问题的影响。
我们提出以下变通办法,以帮助减轻在无法从一个平台切换到另一个平台的情况下发生DoS攻击的风险:
- 通过执行“ sudo ulimit -n createdNumber”来增加文件描述符的限制。
- 使用外部负载平衡器和服务看门狗减少单个实例的负载并关注服务状态。
gRPC的安全建议
随着使用gRPC框架的企业的数量不断增加(由于其可靠性和服务可伸缩性),应该对如何保护该协议免受风险和威胁的认识更加广泛。
尽管gRPC支持系统之间的有效通信,但必须强调的是,确保这些系统之间的通信安全是开发人员的责任。gRPC提供了有关受支持的身份验证机制的全面指南,该机制将与该协议一起使用,例如开发人员应遵循的使用SSL / TLS(具有或不具有基于Google令牌的身份验证)的协议。开发人员还可以选择通过Credentials插件API插入自己的身份验证系统。
开发人员还应该使用将验证内容的安全性解决方案,以确保没有恶意负载能够通过从客户端传输到服务器的消息渗透到系统,反之亦然。
确保企业在传输过程中确保关键数据安全,关注服务状态以及实施身份验证和授权以确保数据安全的解决方案对企业也至关重要。
gRPC框架是开发人员和企业构建API,应用程序和微服务的有效工具。但是,像它的前任一样,它同样可以不受风险和威胁的侵害-因此应该强调对安全解决方案,检查和控制的需求。