Preventing SQL Injection/Good Ruby method - ruby

What is a good method in Ruby to prevent SQL Injection?

in straight up ruby? use prepared statements:
require 'mysql'
db = Mysql.new('localhost', 'user', 'password', 'database')
statement = db.prepare "SELECT * FROM table WHERE field = ?"
statement.execute 'value'
statement.fetch
statement.close

Not just in Ruby - bind your parameters (be it in the database, or in your client code).

Check out the guide they have up on this: http://guides.rubyonrails.org/security.html#injection
Basically, you want to use bind variables in your models to find data, rather than inline parameters..
Model.find(:first, :conditions => ["login = ? AND password = ?", entered_user_name, entered_password])

According to http://ruby.railstutorial.org/ you can prevent Cross Site Request Forgery by inserting the
<%= csrf_meta_tags %>
tag in the header of app/views/layouts/application.html.erb.
Direct link of example

This thread references:
http://www.ruby-forum.com/topic/90258#new
http://www.ruby-forum.com/topic/82349#143790
ActiveRecord's find() method has built in ways to avoid SQL injection by
using the format
> :conditions => [ "user_name = ?", user_name]
Is there any such system for escaping injection in order? It seems to
only take a string and feed it to the SQL statement. This causes a
vulnerability when using params to set : order as in this function:
def list
sort_by = params[:sort_by]
#book_pages, #books = paginate :books,
:order => sort_by,
:per_page => 10
end
We've tried a few methods to sanitize sort_by such as order => ['?',
sort_by] but it just passes that to the SQL statement like a flattened
array. The 'escaping magic' does not work for order. Should I use
gsub! to sanitize params[:sort_by]?

Related

ActiveRecord, find by polymorphic attribute

Having this:
class Event < ActiveRecord::Base
belongs_to :historizable, :polymorphic => true
end
user = User.create!
I can:
Event.create!(:historizable => user)
But I can't:
Event.where(:historizable => user)
# Mysql2::Error: Unknown column 'events.historizable' in 'where clause'
I have to do this instead:
Event.where(:historizable_id => user.id, :historizable_type => user.class.name)
Update
Code that reproduces the issue: https://gist.github.com/fguillen/4732177#file-polymorphic_where_test-rb
This has been implemented in Rails master and will be available in
Rails 4. Thanks.
– #carlosantoniodasilva
I do this:
user.events
This is a proper AR query, you can chain it with other scopes and stuff:
user.events.where(<your event conditions here>)
EDIT: AFAIK the other way around you must specify both fields (makes sense: you could have a user with id 4 and another thing with events, like a Party, also with id 4).
EDIT2: Regarding "Why does create work and where doesn't": create is more highlevel than where, because the former deals with "a complete model", while the latter manages things at the database table level.
ActiveRecord's create (AFAIK) uses a combination of new + update_param somewhere down the line.
update_param uses your model's xxxx= methods for assigning each individual property.
In your example, historizable= is a method built by the belongs_to expression. Since the belongs_to "knows" that it's polymorphic, it can deal with the type and id.
On the other hand, when you pass a hash to the where clause, the parameters there only refer to database fields. Rails provides scopes for "higher level" access:
class Event < ActiveRecord::Base
...
scope :by_historizable, lambda { |h| where(:historizable_id => h.id, :historizable_type => h.class.name) }
end
...
Event.by_historizable(user).where(<your other queries here>)
I've heard that this might change in Rails 4, and where might be more "intelligent". But I have not checked yet.
Try:
Event.joins(:historizable).where(:historizable => {:historizable_type => user})

Parameterizing SQL queries in Ruby + TinyTDS

I am trying to figure out how to parameterize an SQL string before handing it off to be executed, but sadly I find a lot of this on the internet:
sql = "SELECT * FROM table_name WHERE thing LIKE '%#{input}%'"
Which is a bad thing...however, parameterizing sql queries is available in the underlying Sequel library, which is what TinyTDS is built on top of. So I know it's possible. I am just having a hard time figuring it out.
I really wish it could be as simple as this:
#client = TinyTds::Client.new(
:adapter => 'sqlserver',
:host => host,
:database => db,
:username => username,
:password => password)
sql = "SELECT * FROM table_name WHERE thing LIKE ?"
safe_sql = #client.prepare(sql, input)
result = #client.execute(safe_sql)
I seem to have found something called a Dataset class in the sourcecode, which has a prepare method. The question is, how do I use it? Do I need to create another object before handing it off to the execute() method in the #client object? I couldn't find an initialize or a new method, so simple instantiation seems like the wrong way to go.
I implemented the Sequel gem with TinyTds as the adapter. This allows you to parameterize SQL queries. See example below:
require "tiny_tds"
require 'sequel'
DB = Sequel.connect(
adapter: 'tinytds',
host: "dataserver",
database: "database",
user: "username",
password: "password"
)
I then was able to make a SQL insert statement with my values parametrized.
posts_table = DB[:posts]
posts_table.insert(:author => 'John Smith', :title => 'How to parametrize sql queries')
I'm connecting to a MS SQL database.

ActiveRecord conditions across multiple tables.

I'm trying to retrieve cars from my database where each car has a manufacturer, and can have multiple styles.
For example, a ford fiesta is a coupe, sedan and hatch.
I've got my relationships set-up in my models, but now I want to create a query to return the results. The query construction will depend on what parameters are supplied.
This is what I've got so far
conditions = {}
conditions[:manufacturer_id] = params[:manufacturer_id] unless params[:manufacturer_id].blank? # this works!
conditions[:style_id] = "style_id IN (?)", params[:style_ids] unless params[:style_ids].blank? #this breaks it :(
cars = Car.find(:all, :conditions=> conditions)
return render :json => cars
The error getting returned is
PG::Error: ERROR: column cars.style_ids does not exit of course this is because the style_id is in a join table called cars_styles. Is there a way to tell ActiveRecord which table to look for within the condition?
The key thing here is that I want to only have one controller method which takes the params in existence and then creates the right query. So if I don't have a manufacturer_id, it will only query the styles, or if vice versa. Of course, I'll be adding other params later too.
I ended up doing this with scoped queries like this
scope :from_manufacturer, lambda{|manu|{:joins => :manufacturer, :conditions => "manufacturers.id = #{manu}" }}
scope :from_style, lambda{|style|{:joins => :style, :conditions => "styles.id = #{style}"}}
def self.get_cars(params)
scope = self
[:manufacturer,:style].each do |s|
scope = scope.send("from_#{s}", params[s]) if params[s].present?
end
scope
end
Works great!

Better way to query an LDAP users via ruby net-ldap?

Is there a better way to search for users and computers specifically using the Net-ldap gem?
Here is what I am currently having to do to get only users.
results = search :base => #base, :filter => Net::LDAP::Filter.eq("cn", "*")
#results = Array.new
results.each do |result|
#results.push result if result[:objectclass].include? "person" unless result[:objectclass].include? "computer"
Seems like there would be a better way. I can't see anything obvious in the documentation.
You can use the Join filter functionality of net-ldap:
filter = Net::LDAP::Filter.eq("sAMAccountName", "*")
filter2 = Net::LDAP::Filter.eq("objectCategory", "organizationalPerson")
joined_filter = Net::LDAP::Filter.join(filter, filter2)
ldap.search(:base => treebase, :filter => joined_filter) do |entry|
puts entry.sAMAccountName
end
If you know the objectClass that is used for persons, you could use the filter '(objectClass=person)', replacing 'person' with the objectClass. Most implementations will use 'person' or an objectClass that inherits from 'person' such as 'inetOrgPerson'. Using the filter '(cn=*)' will most likely get entries that are not persons.
Try using Filter.eq("objectClass","person")

Trying to call find_by_id on ActiveRecord::Relation, Arel exception

I'm getting to grips with Rails 3 and I can't seem to do a basic find from a result set. My code looks like the following:
#project =
#user.where({:projects => {:project_member_id => user.id}}).find_by_id(params[:id])
I understand that the "where" section will not return a collection but merely create a query that is waiting to be run against the db. However, I can't understand why I get the following error when I try to run the find_by_id:
undefined method `to_sql' for #<Arel::Attributes::String:0x106d9ecf0>
Can somebody point out where I'm going wrong please?
May be you can write something like this:
#project =
#user.where({:projects => {:project_member_id => user.id}}).where(:id => params[:id])
I think it will works.
Alex.
I could be misunderstanding what you are trying to do here, but it looks like you have an association called projects in the user model, right? If so, this is much simpler (and works):
#project = #user.projects.find params[:id]
If you don't have an association setup, you should look into them. There is a great rails guide here on the subject.
I hope this helps.
As you mentioned above, "where" would return ActiveRecord::Relation object, you can check it by running:
#project =
#user.where({:projects => {:project_member_id => user.id}}).class
In order to return a collection of instantiated objects and run find, you can try to force it by running something like:
#project =
#user.where({:projects => {:project_member_id => user.id}}).all.find_by_id(params[:id])
Love method chaining in Rails!
However, this would first find all projects with passed uesr.id (which can be costly, and, probably not what you want)...
Good luck!
Try
#project =
#user.where({:projects => {:project_member_id => user.id}}).where(:id => params[:id]).first
But I dont understand why you are doing all these when you have the primary key with you..just Model.find params[:id] is enough I think (I assume there is something more to it).
Try this:
#project = #user.where({:projects => {:project_member_id => user.id}}).all.find {|p| p.id == params[:id]}

Resources