Class Brakeman::CheckSQL
In: lib/brakeman/checks/check_sql.rb
Parent: Brakeman::BaseCheck

This check tests for find calls which do not use Rails’ auto SQL escaping

For example:

 Project.find(:all, :conditions => "name = '" + params[:name] + "'")

 Project.find(:all, :conditions => "name = '#{params[:name]}'")

 User.find_by_sql("SELECT * FROM projects WHERE name = '#{params[:name]}'")

Methods

Constants

STRING_METHODS = Set[:<<, :+, :concat, :prepend]
IGNORE_METHODS_IN_SQL = Set[:id, :merge_conditions, :table_name, :quoted_table_name, :quoted_primary_key, :to_i, :to_f, :sanitize_sql, :sanitize_sql_array, :sanitize_sql_for_assignment, :sanitize_sql_for_conditions, :sanitize_sql_hash, :sanitize_sql_hash_for_assignment, :sanitize_sql_hash_for_conditions, :to_sql, :sanitize, :primary_key, :table_name_prefix, :table_name_suffix, :where_values_hash, :foreign_key
QUOTE_METHODS = [:quote, :quote_column_name, :quoted_date, :quote_string, :quote_table_name]
AREL_METHODS = [:all, :and, :arel_table, :as, :eq, :eq_any, :exists, :group, :gt, :gteq, :having, :in, :join_sources, :limit, :lt, :lteq, :not, :not_eq, :on, :or, :order, :project, :skip, :take, :where, :with]
SELF_CLASS = s(:call, s(:self), :class)

Public Instance methods

find_by_sql and count_by_sql can take either a straight SQL string or an array with values to bind.

Check call for string building

The ‘find’ methods accept a number of different types of parameters:

 * The first argument might be :all, :first, or :last
 * The first argument might be an integer ID or an array of IDs
 * The second argument might be a hash of options, some of which are
   dangerous and some of which are not
 * The second argument might contain SQL fragments as values
 * The second argument might contain properly parameterized SQL fragments in arrays
 * The second argument might contain improperly parameterized SQL fragments in arrays

This method should only be passed the second argument.

Prior to Rails 2.1.1, the :offset and :limit parameters were not escaping input properly.

www.rorsecurity.info/2008/09/08/sql-injection-issue-in-limit-and-offset-parameter/

Check hash keys for user input. (Seems unlikely, but if a user can control the column names queried, that could be bad)

Checks hash values associated with these keys:

 * conditions
 * order
 * having
 * joins
 * select
 * from
 * lock

joins can take a string, hash of associations, or an array of both(?) We only care about the possible string values.

Model#lock essentially only cares about strings. But those strings can be any SQL fragment. This does not apply to all databases. (For those who do not support it, the lock method does nothing).

Checks each argument to order/reorder/group for possible SQL. Anything used with these methods is passed in verbatim.

Check an interpolated string for dangerous values.

This method assumes values interpolated into strings are unsafe by default, unless safe_value? explicitly returns true.

Look for something like this:

 params[:x].constantize.find('something')

 s(:call,
   s(:call,
     s(:call,
       s(:call, nil, :params, s(:arglist)),
       :[],
       s(:arglist, s(:lit, :x))),
     :constantize,
     s(:arglist)),
   :find,
   s(:arglist, s(:str, "something")))

Check exp for dangerous values. Used by unsafe_sql?

Find calls to named_scope() or scope() in models RP 3 TODO

Process possible SQL injection sites:

 Model#find

 Model#(named_)scope

 Model#(find|count)_by_sql

 Model#all

   Rails 3

 Model#(where|having)
 Model#(order|group)

   Find Options Hash

 Dangerous keys that accept SQL:

 * conditions
 * order
 * having
 * joins
 * select
 * from
 * lock

Checks the given expression for unsafe SQL values. If an unsafe value is found, returns that value (may be the given exp or a subexpression).

Otherwise, returns false/nil.

Returns value if interpolated value is not something safe

[Validate]