A vulnerability has been found in a port you maintain. Please commit
an update and write up a VuXML report. If you need help feel free to
email ports-secur...@freebsd.org,


---------- Forwarded message ----------
From: Aaron Patterson <tenderl...@ruby-lang.org>
Date: 31 May 2012 15:16
Subject: [oss-security] SQL Injection Vulnerability in Ruby on Rails
(CVE-2012-2661)
To: oss-secur...@lists.openwall.com


SQL Injection Vulnerability in Ruby on Rails

There is a SQL injection vulnerability in Active Record, version 3.0
and later. This vulnerability has been assigned the CVE identifier
CVE-2012-2661.

Versions Affected:  3.0.0 and ALL later versions
Not affected:       2.3.14
Fixed Versions:     3.2.4, 3.1.5, 3.0.13

Impact
------
Due to the way Active Record handles nested query parameters, an
attacker can use a specially crafted request to inject some forms of
SQL into your application's SQL queries.

All users running an affected release should upgrade immediately.

Impacted code directly passes request params to the `where` method of
an ActiveRecord class like this:

   Post.where(:id => params[:id]).all

An attacker can make a request that causes `params[:id]` to return a
specially crafted hash that will cause the WHERE clause of the SQL
statement to query an arbitrary table with some value.

Releases
--------
The FIXED releases are available at the normal locations.

Workarounds
-----------
This issue can be mitigated by casting the parameter to an expected
value.  For example, change this:

   Post.where(:id => params[:id]).all

to this:

   Post.where(:id => params[:id].to_s).all

Patches
-------
To aid users who aren't able to upgrade immediately we have provided
patches for the two supported release series.  They are in git-am
format and consist of a single changeset.  We have also provided a
patch for the 3.0 series despite the fact it is unmaintained.

* 3-0-params_sql_injection.patch - Patch for 3.0 series
* 3-1-params_sql_injection.patch - Patch for 3.1 series
* 3-2-params_sql_injection.patch - Patch for 3.2 series

Please note that only the  3.1.x and 3.2.x series are supported at
present.  Users of earlier unsupported releases are advised to upgrade
as soon as possible as we cannot guarantee the continued availability
of security fixes for unsupported releases.

Credits
-------

Thanks to Ben Murphy for reporting the vulnerability to us, and to
Chad Pyne of thoughtbot for helping us verify the fix.

--
Aaron Patterson
http://tenderlovemaking.com/


-- 
Eitan Adler
From 99f030934eb8341db333cb6783d0f42bfa57358f Mon Sep 17 00:00:00 2001
From: Aaron Patterson <aaron.patter...@gmail.com>
Date: Wed, 30 May 2012 15:06:12 -0700
Subject: [PATCH] predicate builder should not recurse for determining where
 columns. Thanks to Ben Murphy for reporting this

CVE-2012-2661
---
 .../active_record/relation/predicate_builder.rb    |    6 +++---
 activerecord/test/cases/relation/where_test.rb     |   19 +++++++++++++++++++
 2 files changed, 22 insertions(+), 3 deletions(-)
 create mode 100644 activerecord/test/cases/relation/where_test.rb

diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb 
b/activerecord/lib/active_record/relation/predicate_builder.rb
index 505c3f4..84e88cf 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -5,17 +5,17 @@ module ActiveRecord
       @engine = engine
     end
 
-    def build_from_hash(attributes, default_table)
+    def build_from_hash(attributes, default_table, check_column = true)
       predicates = attributes.map do |column, value|
         table = default_table
 
         if value.is_a?(Hash)
           table = Arel::Table.new(column, :engine => @engine)
-          build_from_hash(value, table)
+          build_from_hash(value, table, false)
         else
           column = column.to_s
 
-          if column.include?('.')
+          if check_column && column.include?('.')
             table_name, column = column.split('.', 2)
             table = Arel::Table.new(table_name, :engine => @engine)
           end
diff --git a/activerecord/test/cases/relation/where_test.rb 
b/activerecord/test/cases/relation/where_test.rb
new file mode 100644
index 0000000..90c690e
--- /dev/null
+++ b/activerecord/test/cases/relation/where_test.rb
@@ -0,0 +1,19 @@
+require "cases/helper"
+require 'models/post'
+
+module ActiveRecord
+  class WhereTest < ActiveRecord::TestCase
+    fixtures :posts
+
+    def test_where_error
+      assert_raises(ActiveRecord::StatementInvalid) do
+        Post.where(:id => { 'posts.author_id' => 10 }).first
+      end
+    end
+
+    def test_where_with_table_name
+      post = Post.first
+      assert_equal post, Post.where(:posts => { 'id' => post.id }).first
+    end
+  end
+end
-- 
1.7.5.4

From b71d4ab9d7d61ebe3411a8754e9fe93d3587704e Mon Sep 17 00:00:00 2001
From: Aaron Patterson <aaron.patter...@gmail.com>
Date: Wed, 30 May 2012 15:05:19 -0700
Subject: [PATCH] predicate builder should not recurse for determining where
 columns. Thanks to Ben Murphy for reporting this

CVE-2012-2661
---
 .../associations/association_scope.rb              |   17 ++++++++++++++++-
 .../active_record/relation/predicate_builder.rb    |    6 +++---
 activerecord/test/cases/relation/where_test.rb     |   19 +++++++++++++++++++
 3 files changed, 38 insertions(+), 4 deletions(-)
 create mode 100644 activerecord/test/cases/relation/where_test.rb

diff --git a/activerecord/lib/active_record/associations/association_scope.rb 
b/activerecord/lib/active_record/associations/association_scope.rb
index 6cc401e..8e1df35 100644
--- a/activerecord/lib/active_record/associations/association_scope.rb
+++ b/activerecord/lib/active_record/associations/association_scope.rb
@@ -87,7 +87,7 @@ module ActiveRecord
 
             conditions.each do |condition|
               if options[:through] && condition.is_a?(Hash)
-                condition = { table.name => condition }
+                condition = disambiguate_condition(table, condition)
               end
 
               scope = scope.where(interpolate(condition))
@@ -126,6 +126,21 @@ module ActiveRecord
         end
       end
 
+      def disambiguate_condition(table, condition)
+        if condition.is_a?(Hash)
+          Hash[
+            condition.map do |k, v|
+              if v.is_a?(Hash)
+                [k, v]
+              else
+                [table.table_alias || table.name, { k => v }]
+              end
+            end
+          ]
+        else
+          condition
+        end
+      end
     end
   end
 end
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb 
b/activerecord/lib/active_record/relation/predicate_builder.rb
index 7e8ddd1..0e436e8 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -1,16 +1,16 @@
 module ActiveRecord
   class PredicateBuilder # :nodoc:
-    def self.build_from_hash(engine, attributes, default_table)
+    def self.build_from_hash(engine, attributes, default_table, check_column = 
true)
       predicates = attributes.map do |column, value|
         table = default_table
 
         if value.is_a?(Hash)
           table = Arel::Table.new(column, engine)
-          build_from_hash(engine, value, table)
+          build_from_hash(engine, value, table, false)
         else
           column = column.to_s
 
-          if column.include?('.')
+          if check_column && column.include?('.')
             table_name, column = column.split('.', 2)
             table = Arel::Table.new(table_name, engine)
           end
diff --git a/activerecord/test/cases/relation/where_test.rb 
b/activerecord/test/cases/relation/where_test.rb
new file mode 100644
index 0000000..90c690e
--- /dev/null
+++ b/activerecord/test/cases/relation/where_test.rb
@@ -0,0 +1,19 @@
+require "cases/helper"
+require 'models/post'
+
+module ActiveRecord
+  class WhereTest < ActiveRecord::TestCase
+    fixtures :posts
+
+    def test_where_error
+      assert_raises(ActiveRecord::StatementInvalid) do
+        Post.where(:id => { 'posts.author_id' => 10 }).first
+      end
+    end
+
+    def test_where_with_table_name
+      post = Post.first
+      assert_equal post, Post.where(:posts => { 'id' => post.id }).first
+    end
+  end
+end
-- 
1.7.5.4

From 71f7917c553cdc9a0ee49e87af0efb7429759718 Mon Sep 17 00:00:00 2001
From: Aaron Patterson <aaron.patter...@gmail.com>
Date: Wed, 30 May 2012 15:04:11 -0700
Subject: [PATCH] predicate builder should not recurse for determining where
 columns. Thanks to Ben Murphy for reporting this

CVE-2012-2661
---
 .../associations/association_scope.rb              |   17 ++++++++++++++++-
 .../active_record/relation/predicate_builder.rb    |    6 +++---
 activerecord/test/cases/relation/where_test.rb     |   19 +++++++++++++++++++
 3 files changed, 38 insertions(+), 4 deletions(-)
 create mode 100644 activerecord/test/cases/relation/where_test.rb

diff --git a/activerecord/lib/active_record/associations/association_scope.rb 
b/activerecord/lib/active_record/associations/association_scope.rb
index b3819e3..f9cffa4 100644
--- a/activerecord/lib/active_record/associations/association_scope.rb
+++ b/activerecord/lib/active_record/associations/association_scope.rb
@@ -75,7 +75,7 @@ module ActiveRecord
 
             conditions.each do |condition|
               if options[:through] && condition.is_a?(Hash)
-                condition = { table.name => condition }
+                condition = disambiguate_condition(table, condition)
               end
 
               scope = scope.where(interpolate(condition))
@@ -114,6 +114,21 @@ module ActiveRecord
         end
       end
 
+      def disambiguate_condition(table, condition)
+        if condition.is_a?(Hash)
+          Hash[
+            condition.map do |k, v|
+              if v.is_a?(Hash)
+                [k, v]
+              else
+                [table.table_alias || table.name, { k => v }]
+              end
+            end
+          ]
+        else
+          condition
+        end
+      end
     end
   end
 end
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb 
b/activerecord/lib/active_record/relation/predicate_builder.rb
index a789f48..9c84d8a 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -1,16 +1,16 @@
 module ActiveRecord
   class PredicateBuilder # :nodoc:
-    def self.build_from_hash(engine, attributes, default_table)
+    def self.build_from_hash(engine, attributes, default_table, check_column = 
true)
       predicates = attributes.map do |column, value|
         table = default_table
 
         if value.is_a?(Hash)
           table = Arel::Table.new(column, engine)
-          build_from_hash(engine, value, table)
+          build_from_hash(engine, value, table, false)
         else
           column = column.to_s
 
-          if column.include?('.')
+          if check_column && column.include?('.')
             table_name, column = column.split('.', 2)
             table = Arel::Table.new(table_name, engine)
           end
diff --git a/activerecord/test/cases/relation/where_test.rb 
b/activerecord/test/cases/relation/where_test.rb
new file mode 100644
index 0000000..90c690e
--- /dev/null
+++ b/activerecord/test/cases/relation/where_test.rb
@@ -0,0 +1,19 @@
+require "cases/helper"
+require 'models/post'
+
+module ActiveRecord
+  class WhereTest < ActiveRecord::TestCase
+    fixtures :posts
+
+    def test_where_error
+      assert_raises(ActiveRecord::StatementInvalid) do
+        Post.where(:id => { 'posts.author_id' => 10 }).first
+      end
+    end
+
+    def test_where_with_table_name
+      post = Post.first
+      assert_equal post, Post.where(:posts => { 'id' => post.id }).first
+    end
+  end
+end
-- 
1.7.5.4

Attachment: pgp3IkQczAJf1.pgp
Description: PGP signature

_______________________________________________
freebsd-ruby@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-ruby
To unsubscribe, send any mail to "freebsd-ruby-unsubscr...@freebsd.org"

Reply via email to