Security

Here we list tools and best practices that we use at NECOLT to make sure our web apps are as secure as possible.

Rails

    # Add the following to your ApplicationController
    class ApplicationController < ActionController::Base
      protect_from_forgery, with: :exception
    end

    # And add the meta tag to your HTML head
    <%= csrf_meta_tags %>

  • Always escape user-provided data (never call html_safe or raw on user-input without sanitizing first)
    # GOOD: strip all tags and attributes that are not white-listed
    <%= sanitize(@user.name) %>

    # GOOD: data inserted in HTML is automatically escaped
    <% @user.name %>

    # BAD: data will be inserted in HTML without escaping
    <%= @user.name.html_safe %>
  • Avoid common security gotchas when using ActiveRecord methods.
  • Explicitly whitelist attributes in controllers with strong parameters.
  • Use rake secret to generate secret keys for encryption.
  • Use secureheaders to add security-related HTTP headers in responses.
  • Use devise for user authentication and password management.
  • Use bundler-audit to check for vulnerable versions of gems in Gemfile.lock.
  • Remove sensitive information from rails logs by adding rule to config/initializers/filter_parameter_logging.rb.
  • Read about and follow other security conventions in Rails guides.
  • Regularly update libraries and technologies used in projects.

Securing File uploads

  • Whitelist or blacklist extensions and content types in every Carrierwave uploader
    class MyUploader < CarrierWave::Uploader::Base
      def extension_whitelist
        %w(jpg jpeg gif png)
      end
    
      def content_type_whitelist
        %r{image\/}
      end
    
      # alternatively
      def content_type_blacklist
        ['application/text', 'application/json']
      end
    end
    
  • Use ruby-filemagic to properly extract content type
    class ContentTypeExtractor
      def initialize(file)
        @file = file
      end
    
      def filemagic
        @filemagic ||= FileMagic.new(FileMagic::MAGIC_MIME_TYPE)
      end
    
      def extract
        content_type = nil
    
        File.open(@file.path) do |fd|
          data = fd.read(1024) || ''
          content_type = filemagic.buffer(data)
        end
    
        content_type
      end
    end
    

React.js

Node.js

  • Use up-to-date Node.js version.
  • Use helmet to secure Express applications.
  • Use secure cookie storage with strong secret keys. (cookie-session)[https://github.com/expressjs/cookie-session] is a good choice.
  • Ensure dependencies don’t have vulnerabilities. nsp and snyk are good tools to find packages with vulnerabilities.
  • Make sure ORM sanitizes parameters to queries, to prevent SQL injections. Use sqlmap to help detect SQL injection vulnerabilities.

Brakeman

Brakeman is an open source static analysis tool that we use to checks Rails applications for security vulnerabilities.

    bundle exec brakeman -A -q

### Ignore false positives

Brakeman reports some vulnerabilities that are false positives. False positives are warnings about potential vulnerabilities which are not actual vulnerabilities. Before ignoring a false positive, be certain it is actually a false.

The -I option (or –interactive-ignore) is the simplest way to create and manage an ignore configuration.

Authorization

It is important to always check user permissions on resources that users can access or modify.

  • When finding records, always use scopes to ensure proper access to the resources
    class TasksController < ApplicationController
      # GOOD: task search is limited to current users tasks
      expose(:task) { current_user.tasks.find(params[:task_id]) }
    
      # BAD: user can access any task in the database by sending its id the request
      expose(:task) { Task.find(params[:task_id]) }
    end
    
  • When more complicated authorization rules are necessary, use cancancan rubygem

Content encryption

When there is a need to have encrypted content use attr_encrypted to encrypt application data. If necessary, for performance reasons use attr_encrypted_pgcrypto which in turn uses PostgreSQL pgcrypto module to perform encryption and decryption.

Encryption key management

Encryption keys for content encryption should be stored in separate configuration file. This file should not be indexed by git and there should be a corresponding entry for a key file in .gitignore. Each project environment should have its own encryption key.

SSH

  • Use strong passphrases (e.g. multiple words separated with special symbols) when generating ssh keys.

Using Passwords

  • Use specific tool to generate random passwords (1password, pqgen, keepass.info).

HTTPS

  • Use HTTPS rather HTTP.