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]}'")
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) |
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")))
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.