Rails: HOST Header攻击漏洞



我很担心我开发的web应用的安全性,所以我一直在使用各种工具来抓取我的每个应用。

虽然一切都可以在编程方面完成,并且不是由现成的类预见,如活动记录,是完成的,有一个问题我不断得到警报,我不知道从哪里开始修复这个。

我在NginxRails 4.1后面运行Unicorn。我一直收到的警告是:

    An attacker can manipulate the Host header as seen by the 
web application and cause the application to behave in 
unexpected ways. Developers often resort to the exceedingly 
untrustworthy HTTP Host header (_SERVER["HTTP_HOST"] in PHP). 
Even otherwise-secure applications trust this value enough to 
write it to the page without HTML-encoding it with code equivalent to:
<link href="https://_SERVER['HOST']" (Joomla)
...and append secret keys and tokens to links containing it:
(Django, Gallery, others)
....and even directly import scripts from it:
(Various) 

提出以下建议:

The web application should use the SERVER_NAME instead
of the Host header. It should also create a dummy vhost 
that catches all requests with unrecognized Host headers. 
This can also be done under Nginx by specifying a non-wildcard 
SERVER_NAME, and under Apache by using a non-wildcard serverName 
and turning the UseCanonicalName directive on. Consult references 
for detailed information.

确定,不管. .据我所知,这个漏洞通常是无害的,但可能对各种web应用程序有害,这取决于它们的类型。

我怎么做才能阻止这种攻击?谢谢你的建议。

我找到了一种绕过该行为并停止接收警报的方法。我不知道这是不是最好的方法,所以评论、建议和新的答案都可以接受。

开始了。

application_controller.rb

class ApplicationController < ActionController::Base
    before_action :debug_headers
private
    def debug_headers
        if request.env['HTTP_X_FORWARDED_HOST']
            request.env.except!('HTTP_X_FORWARDED_HOST') # just drop the variable
        end
    end # def
end # class

允许可疑请求到达您的代码不是最佳实践;你让自己暴露在所有你闻所未闻的攻击之下。主机报头欺骗会导致非常严重的问题,应该防止这些攻击。也就是说,这个答案最好放在ServerFault;)中。

一个流行且简单的修复方法是通过简单地忽略具有可疑主机头的传入请求来完全避免这个问题。在安全性方面,您希望忽略每个主机头与您的系统不完全匹配的请求。在Nginx中,这是通过在端口80(如果你使用HTTPS,端口443)上设置一个默认服务器来完成的,除了返回444(一个非标准的Nginx代码,大致翻译为"COLD SHOULDER")之外什么都不做:

server {
    listen 80 default_server;
    listen 443 default_server;
    return 444;
}

与此相关的一个问题是,某些托管解决方案(如AWS)在主机报头中提供动态IP地址的自动运行状况/延迟检查。如果您放弃这些请求,您的实例将从负载均衡器中删除,并且您无法从web浏览器访问您的站点。您需要在默认服务器中放置逻辑以传递这些请求并忽略所有其他请求。

作为某种中间件可能会更好:

# config/environments/production.rb
config.action_controller.default_url_options = { host: "example.com" }

:

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :protect_from_host_header_attack
  def protect_from_host_header_attack
    env['HTTP_HOST'] = default_url_options.fetch(:host, env['HTTP_HOST'])
  end
end

最新更新