I want to sanitize the data coming from my form in ActiveRecord. Especially the apostrophe before its actually included into the SQL query. I want it to be something raghu'\s if raghu's is been inputed. I have already tried using:
sanitize_sql_array
sanitize_sql_for_assignment
sanitize_sql_for_conditions
sanitize_sql_hash_for_assignment
sanitize_sql_hash_for_conditions
But none of these seem to escape the apostrophe there by failing my SQL query.
Rails will handle a lot of the santizing for you if you use the following format for performing finds. It'll run the necessary sub methods to ensure that nothing potentially destructive is inserted into the database. Not sure about the single inverted comma, but it's worth a shot.
Model.find(:all, :condition => ["text_value = ?", params[:form_input])
You might want to have a look at this thread - Strip & Sanitize BEFORE saving data from the Ruby Forum - I haven't tried any of the solutions mentioned but it might get you going in the right direction
Related
I got a little problem using the LIKE sentence on rails i know that this next sentence works:
Brand.find(:all, :joins=>[:cars], :conditions=>["brandname LIKE ?","%ford%"])
But it's any way around that I could to something like this:
Brand.find(:all, :joins=>[:cars], :conditions=>["brandname LIKE '%ford%'"])
Its because i already have a function that returns all conditions on a single string, but i require to support search in strings and i don't really how to get it work.
Any help will be appreciated.
I'm not entirely certain that I understand what you're talking about. Are you trying to pass in a variable into the conditions?
I would re-write this query just a tad.
Brand.all.joins(:cars).where("brandname LIKE ?", "%#{some_variable}%")
Of course selecting all can be bad for performance if you get a lot of records so you may want to consider limiting that or paginating the results somehow.
I would recommend the guides. Using an array would be great in this instance
Brand.all.joins(:cars).where("brandname LIKE ?", "%#{params[:brand_search]}%")
There was a very similar question before but i still struggle.
Is it possible to build a query up in stages?
Let's say I have a search form with many text and select fields that may be chained with and/or or which could be blank.
So the sql statement should consist of several parts that are connected individually for each search.
I tried to create strings for every option and put them to a symbol? (i mean #options) and put that in the where clause (e.g. Product.where(#options) ). That works somehow but i have got troubles with this part: 'params[:query]' when it's in quotes. Either my sql statement says 'select products from products where (name like params[:query]') or if i try #{params[:query]} it says: select products from products (where 'name' like ''.)
So how can i chain different parts of a query?
I looking forward to your answers!
Never, ever, ever embed raw strings in your SQL. This is extremely bad form. You should always use the escaping mechanism provided by Rails or something equivalent to avoid ending up in serious trouble. Inserting content from params is very dangerous and should never be done as it only takes this to nuke your app: { :query => '\"-- DROP TABLE users;' }
Generally you use the helper methods provided by ActiveRecord to build up your query in stages:
scope = Product
if (params[:query].present?)
scope = scope.where([ 'name LIKE ?', "%#{params[:query]}%" ])
end
if (params[:example].present?)
scope = scope.where(:example => true)
end
#products = scope.all
You can build it up in stages like this, modifying the scope in-place each time, and then execute the final call to retrieve it. Generally that's when you use your paginator to split up the results.
It's okay to put pretty much anything in your options because it should be escaped by the time it hits the SQL phase, much as anything on the HTML side is escaped for you as well.
Don't confuse instance variables like #options with a symbol like :query. The two are very different things. Instance variables have the benefit of propagating to your view automatically, so they are often used extensively in controllers. Views should avoid modifying them whenever possible as a matter of style.
I'm doing queries like this in Rails 3.x
Speaker.where("name like '%yson%'")
but I'd love to avoid the DB specific code. What's the right way to do this?
If there's a way to do this in Rails 2.x too, that would help too.
In Rails 3 or greater
Speaker.where("name LIKE ?", "%yson%")
In Rails 2
Speaker.all(:conditions => ["name LIKE ?", "%yson%"])
Avoid to directly interpolate strings because the value won't be escaped and you are vulnerable to SQL injection attacks.
You can use .matches for it.
> t[:name].matches('%lore').to_sql
=> "\"products\".\"name\" LIKE '%lore'"
Actual usage in a query would be:
Speaker.where(Speaker.arel_table[:name].matches('%lore'))
Use a search engine like solr or sphinx to create indexes for the columns you would be performing like queries on. Like queries always result in a full table scan when you look at the explain plan so you really should almost never use them in a production site.
Not by default in Rails, since there are so many DB options (MySQL, Postgresql, MongoDB, CouchDB...), but you can check out gems like MetaWhere, where you can do things like:
Article.where(:title.matches => 'Hello%', :created_at.gt => 3.days.ago)
=> SELECT "articles".* FROM "articles" WHERE ("articles"."title" LIKE 'Hello%')
AND ("articles"."created_at" > '2010-04-12 18:39:32.592087')
In general though you'll probably have to have some DB specific code, or refactor your code (i.e redefine the .matches operator on symbols in MetaWhere) to work with a different database. Hopefully you won't be changing your database that often, but if you are you should have a centralized location where you define these operators for re-use. Keep in mind that an operator or function defined in one database might not be available in another, in which case having this generalized operation is moot since you won't be able to perform the search anyways.
Suppose I've got a search box on a page in a Rails 3 app where you can search for a client by business name or city. In my controller's index method I do this:
if params[:search]
#clients = Client.where("clients.business_name LIKE :business_name OR clients.city = :city", :business_name => "%#{params[:search]}%", :city => params[:search])
Those hash values get substituted into the SQL and surrounded in quotes. If my input into the search box includes quotes or other dangerous characters, I'll see them being escaped in the development log, like:
...WHERE (clients.business_name LIKE '%Something\' DROP TABLE Foo%'...
Or
...WHERE... OR clients.city = 'Something OR 1=1')
So, since the OR 1=1 is inside the quotes Rails adds, it just produces no match for the city name, and since the quote in the DROP TABLE attempt is escaped, it also produces no match for the business name.
This isn't using actual prepared statements, where the query is sent to the database first without the search values filled in, then subsequently, the search values are sent to the database to fill in. I thought that was the safest approach, but Rails doesn't do it; I think this is because it's not available in all databases and implementations vary.
Is this open to SQL injection in some way? I don't see it, but again, it's not using prepared statements, so I wonder. If there's a vulnerability, how could I do this more safely?
No, there's not a SQL injection vulnerability here. ActiveRecord will call connection.quote on the values of the hash that you passed in as the second parameter to where, so you are safe.
The only potential SQL injection point I could think of would be if there were some undiscovered bug in connection.quote, which is pretty unlikely.
I have a bunch of SQL statements to execute on a database. (I'm doing things that Rails doesn't provide methods for, as far as I know: creating views, adding foreign keys, etc. It's mostly for non-Rails interaction with the data.) In essence, I'm doing the following:
sql = "statement_1; statement_2; statement_3; etc;"
ActiveRecord::Base.connection.execute(sql)
Or with newlines, like so:
sql = <<EOF
statement_1;
statement_2;
statement_3;
etc;
EOF
ActiveRecord::Base.connection.execute(sql)
(Obviously, these statements are just place holders, but I don't think their content matters, according to my tests.)
In either case, only the first statement is executed and the others seem to be ignored. Is that what's going on? I'm only seeing the effects of the first statement whenever I try more than one at a time. Do I need to execute each one separately? One set of statements is coming from a file, so it'd be nice to just load the contents of the file and execute. If there are better strategies I could adopt, I'd be interested in them.
I was hoping the documentation on execute would shed some light, but besides using the singular ("statement"), it doesn't. Perhaps it's because of the database engine I'm using? (For reference, I'm using SQLite at the moment.)
UPDATE: I ended up writing a method that does the following:
def extract_sql_statements(sql)
statements = []
sql.split(';').each do |statement|
statement.strip!
unless statement.empty?
statement += ';'
statements << statement
end
end
return statements
end
...and then looping over statements. It's fixed the problem, but if there are more elegant solutions, I would be interested in hearing about them.
If you look at the rails code then you will find that execute method runs the passed sql, so it should essentially run all your queries as long as they are ';' separated and valid.
EDIT: Sorry! No it won't because it will add ';' in between your query string and complain about wrong syntax