Rating:

题目的确比较脑洞,其中抽象的漏洞模型在现实世界的Rails应用中不太可能出现(至少出题人没有见过这个场景)。

让我们梳理一下题面。访问`/getflag`会被WAF ban掉,而带入参数`debug={HEADER_PAIR}`,则`HEADER_PAIR`被注入到响应头中。根据hint1,路由DSL如下:
```ruby=
Waf::Engine.routes.draw do
get '*all', to: 'requests#block'
end

get 'getflag', to: 'application#getflag'

```

当Rails匹配到WAF的路由,则交给WAF处理,而WAF本身拦截对任意路径的请求,对`/getflag`路径的请求处理后将不再交给`application`控制器处理。因此,我们的目的是让路由命中:
```ruby=
get 'getflag', to: 'application#getflag'
```
。在真实环境中,恐怕不会有WAF作为一个Rails Engine存在,不管是从性能还是代码复杂度上考虑,更实际的形式是Rack中间件,例如`Rack::Attack`。

响应头注入显然存在于WAF中。hint2提醒我们去寻找Rails路由中的一些约定,这也是最难被找到的地方。这个约定可在Rails[对路由处理的源码](https://github.com/rails/rails/blob/c7620bb9dee7f217f45a511a5d14e12c803c9e94/actionpack/lib/action_dispatch/journey/router.rb#L52)中找到:
```ruby=
status, headers, body = route.app.serve(req) # 将请求交给Rails app并获取响应信息

if "pass" == headers["X-Cascade"]
req.script_name = script_name
req.path_info = path_info
req.path_parameters = set_params
next
end
```
当Rails应用处理完请求后,路由调度器检查响应头中是否存在值为`pass`的键`X-Cascade`(需显式指定),如果有,则继续搜索下一条匹配规则的路由,若找到另一条,则交由对应的应用处理。因此,如果我们通过响应头注入漏洞注入`X-Cascade`到WAF响应中,则Rails继续搜索下一条路由,
```ruby=
get 'getflag', to: 'application#getflag'
```
将被命中,WAF也被绕过了,这里简单过滤了一下'-',不过在rails里请求头键连接符可以用下划线代替,最终获取到flag。