bk-bcs icon indicating copy to clipboard operation
bk-bcs copied to clipboard

[bug] grpc-gateway POST请求触发随机路由问题

Open Lwxiang opened this issue 3 years ago • 0 comments

背景

service层部分组件使用了grpc-gateway,用来在支持grpc协议的同时,额外导出一个http端口,并实现自动转换。 访问http端口的请求,会被grpc-gateway解析并匹配到与proto中配置一致的路由上。

问题

grpc-gateway支持在POST表单时,允许请求“fallback”到相同路由的其他method上,这在初始化时是默认开启的。 简言之,当http请求为POST且带有Content-Type: application/x-www-form-urlencoded的header时,如果server没有注册POST-handler,则会默认fallback到相同路由下的其他method处理。同时,由于grpc-gateway的路由mux实现是保存在map中的,遍历到第一个同路由method时就会执行fallback,结合golang中map遍历的随机性,这会导致以下场景下的随机路由问题:

  • server定义了某一条资源路由规则下的get/put/delete handler,但没有post
  • 用户错误地发起一个post请求到该资源,并且带了Content-Type: application/x-www-form-urlencoded(这在curl -d的情况下是默认的行为)。
  • 预期中,由于该资源路由下我们没有定义post handler,应该返回405 METHOD NOT ALLOWED,但事实上,grpc-gateway会随机地把请求打到该资源路由下的get/put/delete handler上。

虽然当前bcs几乎没有表单POST的场景,但这是一个极大的安全隐患,带来的随机性和不确定性对服务数据有很大的威胁(一个错误的提交可能会删掉所有的数据)。

影响范围

当前直到v2.7.3的grpc-gateway版本都有这个默认开启的问题,bcs-service用到grpc-gateway的组件都存在这个问题。

解决办法

grpc-gateway默认开启的PathLengthFallback功能决定了这个行为,我们并不需要这个功能,因此我们在初始化grpc-gateway的时候,使用WithDisablePathLengthFallback选项手动将其关闭,即可规避这个问题。

rmMux := ggRuntime.NewServeMux(
    ...
    ggRuntime.WithDisablePathLengthFallback(),
)

各个模块可以参考bcs-helm-manager的commit来处理。

Lwxiang avatar Jan 26 '22 02:01 Lwxiang