Sinatra和机架保护设置

Dav*_*zar 16 rack sinatra http-status-code-403

我正在使用Sinatra和CORS接受域A(hefty.burger.com)上的文件上传.域B(fizzbuzz.com)有一个表单,可以将文件上传到A上的路由.

我有一个选项路线和一个后期路线,都命名为'/ uploader'.

options '/uploader' do
  headers 'Access-Control-Allow-Origin' => 'http://fizz.buzz.com',
  'Access-Control-Allow-Methods' => 'POST'
  200
end 

post '/uploader' do
  ... 
  content_type :json
  [{:mary => 'little lamb'}].to_json
end
Run Code Online (Sandbox Code Playgroud)

这些选项首先被击中......然后它会起作用..然后帖子被击中并返回403.

如果我禁用保护,帖子工作......我需要从列表中排除什么样的保护以保持保护但允许这些帖子通过?

我最近才被新的机架防护装置狠狠地踩到了Heroku并让我感到悲伤......任何人都有一个很好的指针,可以在这里做什么?我这么说的原因是,我突然看到日志条目带有会话劫持问题的警报(几乎可以肯定是因为只为应用程序运行> 1 Dyno).我在我的Gemfile.lock中看到了机架保护(1.2.0),即使我从未要求它...我的清单中的某些内容正在调用它,因此它已加载,但我的Sinatra应用程序中的任何内容都没有尝试要求它或者设置它.

Rya*_*yan 18

在Sinatra应用程序中使用它可以解决您的问题:

set :protection, :except => [:json_csrf]
Run Code Online (Sandbox Code Playgroud)

一个更好的解决方案可能是将Sinatra升级到1.4,它使用Rack :: Protection 1.5并且不应该导致你看到的问题.

问题是,当您使用Content-Type:application/json进行响应时,您的RackProtection::JsonCsrfin 版本与CORS不兼容.以下是机架保护中旧的json_csrf.rb的片段:

def call(env)
  status, headers, body = app.call(env)
  if headers['Content-Type'].to_s.split(';', 2).first =~ /^\s*application\/json\s*$/
    if referrer(env) != Request.new(env).host
      result = react(env)
      warn env, "attack prevented by #{self.class}"
    end
  end
  result or [status, headers, body]
end
Run Code Online (Sandbox Code Playgroud)

application/json当引用者与服务器不在同一主机上时,您可以看到此拒绝具有响应的请求.

这个问题在更高版本的机架保护中得到了解决,它现在考虑请求是否是XMLHttpRequest:

   def has_vector?(request, headers)
    return false if request.xhr?
    return false unless headers['Content-Type'].to_s.split(';', 2).first =~ /^\s*application\/json\s*$/
    origin(request.env).nil? and referrer(request.env) != request.host
  end
Run Code Online (Sandbox Code Playgroud)

如果您使用的是Sinatra 1.3.2且无法升级,则解决方法是禁用此特定保护.使用CORS,您可以明确启用跨域XHR请求.Sinatra允许您完全禁用保护,或禁用特定组件Rack::Protection(请参阅Sinatra文档中的"配置攻击保护").

Rack::Protection提供12个中间件组件,帮助抵御常见攻击:

  • Rack::Protection::AuthenticityToken
  • Rack::Protection::EscapedParams
  • Rack::Protection::FormToken
  • Rack::Protection::FrameOptions
  • Rack::Protection::HttpOrigin
  • Rack::Protection::IPSpoofing
  • Rack::Protection::JsonCsrf
  • Rack::Protection::PathTraversal
  • Rack::Protection::RemoteReferrer
  • Rack::Protection::RemoteToken
  • Rack::Protection::SessionHijacking
  • Rack::Protection::XssHeader

在写这篇文章的时候,这些所有,但四个当你使用机架::保护中间件自动加载(Rack::Protection::AuthenticityToken,Rack::Protection::FormToken,Rack::Protection::RemoteReferrer,并Rack::Protection::EscapedParams必须明确添加).

Sinatra使用Rack :: Protection的默认设置,一个例外:它只会添加SessionHijackingRemoteToken启用会话.

最后,如果您正在尝试将CORS与Sinatra一起使用,您可以尝试使用rack-cors,它会为您处理大量细节.


Mar*_*cny 5

如果您看到此问题,则说明您没有使用 CORS(跨源资源共享),并且位于反向代理(例如 nginx 或 apache)后面,请确保您的反向代理没有剥离host标头并替换它与本地主机。

例如,在 nginx 中您需要使用proxy_set_header

location / {
    proxy_pass http://localhost:9296;
    proxy_set_header Host $host;
}
Run Code Online (Sandbox Code Playgroud)

当从请求中删除标头时,Rack::Protection 认为这是 CSRF 攻击。


al3*_*ull 1

这是因为您没有在选项路由中返回允许的方法吗?

这里有一个问题指的是它,它记录了允许的方法。

这里的扩展和这里的中间件可能会帮助你。