Insecure or unset HTTP headers - CORS - Ruby

Insecure or unset HTTP headers - CORS - Ruby

Need

Enforcement of secure and specific HTTP headers for Cross-Origin Resource Sharing (CORS)

Context

  • Requirement of Ruby version 2.0 or higher
  • Usage of Rails for building web applications
  • Usage of rack-cors for enabling Cross-Origin Resource Sharing (CORS) in a Rack-based application

Description

Non compliant code

        # config/application.rb
module YourApp
  class Application < Rails::Application
    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins '*'
        resource '*', :headers => :any, :methods => [:get, :post, :delete, :put, :patch, :options, :head]
      end
    end
  end
end
        
        

The above code represents a CORS (Cross-Origin Resource Sharing) policy that is insecure due to the use of wildcards (*) in the origins and resource fields.

In the CORS policy, the origins field defines which domains are allowed to access resources on the server. By using a wildcard (*), the policy is essentially allowing any domain to access resources. This is a significant security risk as it allows potentially malicious websites to make requests to the server and access sensitive data.

Similarly, the resource field defines which resources can be accessed by the specified origins. Again, by using a wildcard (*), the policy is allowing any resource to be accessed, further increasing the potential for data exposure.

The methods field defines which HTTP methods (GET, POST, DELETE, etc.) can be used in cross-origin requests. In this case, all methods are allowed, which is also a potential security risk.

This code is vulnerable as it does not restrict access to the server's resources, potentially leading to unauthorized access and data breaches. It's recommended to specify only trusted domains in the origins field, limit the resources that can be accessed, and restrict the HTTP methods that can be used.

Steps

  • Remove the wildcard (*) from the 'origins' configuration in the CORS middleware.
  • Specify the allowed domains explicitly in the 'origins' configuration.
  • Update the 'methods' configuration to only include the necessary HTTP methods.
  • Add additional headers to the 'headers' configuration if required.
  • Consider using a whitelist approach instead of allowing all domains.

Compliant code

        # config/application.rb
module YourApp
  class Application < Rails::Application
    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins 'example.com', 'another-domain.com' # replace with your actual domains
        resource '*', :headers => :any, :methods => [:get, :post, :options, :head]
      end
    end
  end
end
        
        

The updated code now specifies the allowed origins explicitly instead of using a wildcard (*). This means that only the specified domains ('example.com', 'another-domain.com') are allowed to share resources. This is a more secure approach as it prevents any arbitrary domain from accessing your resources.

The resource method is also updated to only include the necessary HTTP methods. In this case, only GET, POST, OPTIONS, and HEAD requests are allowed. This reduces the attack surface by limiting the types of requests that can be made.

The headers configuration is left as :any, which means that any type of headers can be included in the request. If you want to further secure your application, you can specify the allowed headers explicitly.

This approach is known as a whitelist approach, where only specified entities are allowed access. This is generally more secure than a blacklist approach, where all entities are allowed access except those specified.

References