Skip to content

Commit

Permalink
:conditions => where
Browse files Browse the repository at this point in the history
  • Loading branch information
amatsuda committed Jul 7, 2011
1 parent b2816ae commit 4d4819f
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 18 deletions.
2 changes: 1 addition & 1 deletion activerecord/lib/active_record/errors.rb
Expand Up @@ -87,7 +87,7 @@ class InvalidForeignKey < WrappedDatabaseException
# #
# For example, in # For example, in
# #
# Location.all :conditions => ["lat = ? AND lng = ?", 53.7362] # Location.where("lat = ? AND lng = ?", 53.7362)
# #
# two placeholders are given but only one variable to fill them. # two placeholders are given but only one variable to fill them.
class PreparedStatementInvalid < ActiveRecordError class PreparedStatementInvalid < ActiveRecordError
Expand Down
17 changes: 5 additions & 12 deletions railties/guides/source/debugging_rails_applications.textile
Expand Up @@ -480,11 +480,7 @@ class Author < ActiveRecord::Base


def find_recent_comments(limit = 10) def find_recent_comments(limit = 10)
debugger debugger
@recent_comments ||= comments.find( @recent_comments ||= comments.where("created_at > ?", 1.week.ago).limit(limit)
:all,
:conditions => ["created_at > ?", 1.week.ago],
:limit => limit
)
end end
end end
</ruby> </ruby>
Expand All @@ -509,13 +505,10 @@ With the code stopped, take a look around:
(rdb:1) list (rdb:1) list
[6, 15] in /PathTo/project/app/models/author.rb [6, 15] in /PathTo/project/app/models/author.rb
6 debugger 6 debugger
7 @recent_comments ||= comments.find( => 7 @recent_comments ||= comments.where("created_at > ?", 1.week.ago).limit(limit)
8 :all, 8 end
9 :conditions => ["created_at > ?", 1.week.ago], 9 end
10 :limit => limit 10 ...
=> 11 )
12 end
13 end
</shell> </shell>


You are at the end of the line, but... was this line executed? You can inspect the instance variables. You are at the end of the line, but... was this line executed? You can inspect the instance variables.
Expand Down
10 changes: 5 additions & 5 deletions railties/guides/source/security.textile
Expand Up @@ -649,7 +649,7 @@ h5(#sql-injection-introduction). Introduction
SQL injection attacks aim at influencing database queries by manipulating web application parameters. A popular goal of SQL injection attacks is to bypass authorization. Another goal is to carry out data manipulation or reading arbitrary data. Here is an example of how not to use user input data in a query: SQL injection attacks aim at influencing database queries by manipulating web application parameters. A popular goal of SQL injection attacks is to bypass authorization. Another goal is to carry out data manipulation or reading arbitrary data. Here is an example of how not to use user input data in a query:


<ruby> <ruby>
Project.all(:conditions => "name = '#{params[:name]}'") Project.where("name = '#{params[:name]}'")
</ruby> </ruby>


This could be in a search action and the user may enter a project's name that he wants to find. If a malicious user enters ' OR 1 --, the resulting SQL query will be: This could be in a search action and the user may enter a project's name that he wants to find. If a malicious user enters ' OR 1 --, the resulting SQL query will be:
Expand Down Expand Up @@ -681,7 +681,7 @@ h5. Unauthorized Reading
The UNION statement connects two SQL queries and returns the data in one set. An attacker can use it to read arbitrary data from the database. Let's take the example from above: The UNION statement connects two SQL queries and returns the data in one set. An attacker can use it to read arbitrary data from the database. Let's take the example from above:


<ruby> <ruby>
Project.all(:conditions => "name = '#{params[:name]}'") Project.where("name = '#{params[:name]}'")
</ruby> </ruby>


And now let's inject another query using the UNION statement: And now let's inject another query using the UNION statement:
Expand All @@ -703,18 +703,18 @@ Also, the second query renames some columns with the AS statement so that the we


h5(#sql-injection-countermeasures). Countermeasures h5(#sql-injection-countermeasures). Countermeasures


Ruby on Rails has a built-in filter for special SQL characters, which will escape ' , " , NULL character and line breaks. <em class="highlight">Using +Model.find(id)+ or +Model.find_by_some thing(something)+ automatically applies this countermeasure</em>. But in SQL fragments, especially <em class="highlight">in conditions fragments (+:conditions => "..."+), the +connection.execute()+ or +Model.find_by_sql()+ methods, it has to be applied manually</em>. Ruby on Rails has a built-in filter for special SQL characters, which will escape ' , " , NULL character and line breaks. <em class="highlight">Using +Model.find(id)+ or +Model.find_by_some thing(something)+ automatically applies this countermeasure</em>. But in SQL fragments, especially <em class="highlight">in conditions fragments (+where("...")+), the +connection.execute()+ or +Model.find_by_sql()+ methods, it has to be applied manually</em>.


Instead of passing a string to the conditions option, you can pass an array to sanitize tainted strings like this: Instead of passing a string to the conditions option, you can pass an array to sanitize tainted strings like this:


<ruby> <ruby>
Model.first(:conditions => ["login = ? AND password = ?", entered_user_name, entered_password]) Model.where("login = ? AND password = ?", entered_user_name, entered_password).first
</ruby> </ruby>


As you can see, the first part of the array is an SQL fragment with question marks. The sanitized versions of the variables in the second part of the array replace the question marks. Or you can pass a hash for the same result: As you can see, the first part of the array is an SQL fragment with question marks. The sanitized versions of the variables in the second part of the array replace the question marks. Or you can pass a hash for the same result:


<ruby> <ruby>
Model.first(:conditions => {:login => entered_user_name, :password => entered_password}) Model.where(:login => entered_user_name, :password => entered_password).first
</ruby> </ruby>


The array or hash form is only available in model instances. You can try +sanitize_sql()+ elsewhere. _(highlight)Make it a habit to think about the security consequences when using an external string in SQL_. The array or hash form is only available in model instances. You can try +sanitize_sql()+ elsewhere. _(highlight)Make it a habit to think about the security consequences when using an external string in SQL_.
Expand Down

0 comments on commit 4d4819f

Please sign in to comment.