【问题标题】:Rails: HOST Header Attack vulnerabilityRails:HOST Header 攻击漏洞
【发布时间】:2014-09-14 05:52:26
【问题描述】:

我非常担心我构建的网络应用程序的安全性,因此我一直在使用各种工具来抓取我的每个应用程序。

虽然在编程方面可以完成的所有事情,以及像 Active Record 这样的现成类没有预见到的事情都已经完成,但有一个问题我不断收到警报,我不知道从哪里开始解决这个问题。

我在 Unicorn 后面运行 NginxRails 4.1。我不断收到的警报是这样的:

    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.

当然,无论如何.. 据我了解,这种漏洞通常是无害的,但在各种网络应用程序中可能是有害的,具体取决于它们的种类。

我该怎么做才能阻止这种攻击?感谢您的任何建议。

【问题讨论】:

    标签: ruby-on-rails security ruby-on-rails-4 nginx


    【解决方案1】:

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

    我们开始吧。

    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
    

    【讨论】:

      【解决方案2】:

      允许可疑请求访问您的代码并不是最佳做法;你让自己对所有你还没有听说过的攻击持开放态度。主机头欺骗会导致非常严重的问题,应该防止这些攻击。话虽如此,这个答案可能更好地放在 ServerFault 中;)。

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

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

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

      【讨论】:

        【解决方案3】:

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

        # 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
        

        【讨论】:

          猜你喜欢
          • 2015-04-16
          • 2017-09-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多