Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Backport offset/limit SQL injection fix to 2-0-stable

Signed-off-by: Michael Koziarski <michael@koziarski.com>
  • Loading branch information...
commit 213f31513e4cb640fa3ed45f387f221401023646 1 parent 760d525
@jonleighton jonleighton authored NZKoz committed
View
9 activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
@@ -106,11 +106,16 @@ def add_limit!(sql, options)
# SELECT * FROM suppliers LIMIT 10 OFFSET 50
def add_limit_offset!(sql, options)
if limit = options[:limit]
- sql << " LIMIT #{limit}"
+ sql << " LIMIT #{sanitize_limit(limit)}"
if offset = options[:offset]
- sql << " OFFSET #{offset}"
+ sql << " OFFSET #{offset.to_i}"
end
end
+ sql
+ end
+
+ def sanitize_limit(limit)
+ limit.to_s[/,/] ? limit.split(',').map{ |i| i.to_i }.join(',') : limit.to_i
end
# Appends a locking clause to an SQL statement.
View
3  activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -318,10 +318,11 @@ def rollback_db_transaction #:nodoc:
def add_limit_offset!(sql, options) #:nodoc:
if limit = options[:limit]
+ limit = sanitize_limit(limit)
unless offset = options[:offset]
sql << " LIMIT #{limit}"
else
- sql << " LIMIT #{offset}, #{limit}"
+ sql << " LIMIT #{offset.to_i}, #{limit}"
end
end
end
View
20 activerecord/test/adapter_test.rb
@@ -103,4 +103,24 @@ def test_reset_table_with_non_integer_pk
end
end
+ def test_add_limit_offset_should_sanitize_sql_injection_for_limit_without_comas
+ sql_inject = "1 select * from schema"
+ assert_equal " LIMIT 1", @connection.add_limit_offset!("", :limit=>sql_inject)
+ if current_adapter?(:MysqlAdapter)
+ assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
+ else
+ assert_equal " LIMIT 1 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
+ end
+ end
+
+ def test_add_limit_offset_should_sanitize_sql_injection_for_limit_with_comas
+ sql_inject = "1, 7 procedure help()"
+ if current_adapter?(:MysqlAdapter)
+ assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject)
+ assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=> '1 ; DROP TABLE USERS', :offset=>7)
+ else
+ assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject)
+ assert_equal " LIMIT 1,7 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
+ end
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.