Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [day] [month] [year] [list]
Date: Mon, 25 Jan 2016 11:30:43 -0800
From: Aaron Patterson <tenderlove@...y-lang.org>
To: security@...e.de, rubyonrails-security@...glegroups.com,
	oss-security@...ts.openwall.com, ruby-security-ann@...glegroups.com
Subject: [CVE-2015-7576] Timing attack vulnerability in basic authentication
 in Action Controller.

Timing attack vulnerability in basic authentication in Action Controller.

There is a timing attack vulnerability in the basic authentication support
in Action Controller. This vulnerability has been assigned the CVE
identifier CVE-2015-7576.

Versions Affected:  All.
Not affected:       None.
Fixed Versions:     5.0.0.beta1.1, 4.2.5.1, 4.1.14.1, 3.2.22.1

Impact
------
Due to the way that Action Controller compares user names and passwords in
basic authentication authorization code, it is possible for an attacker to
analyze the time taken by a response and intuit the password.

For example, this string comparison:

  "foo" == "bar"

is possibly faster than this comparison:

  "foo" == "fo1"

Attackers can use this information to attempt to guess the username and
password used in the basic authentication system.

You can tell you application is vulnerable to this attack by looking for
`http_basic_authenticate_with` method calls in your application.

All users running an affected release should either upgrade or use one of
the workarounds immediately.

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

Workarounds
-----------
If you can't upgrade, please use the following monkey patch in an initializer
that is loaded before your application:

```
$ cat config/initializers/basic_auth_fix.rb
module ActiveSupport
  module SecurityUtils
    def secure_compare(a, b)
      return false unless a.bytesize == b.bytesize

      l = a.unpack "C#{a.bytesize}"

      res = 0
      b.each_byte { |byte| res |= byte ^ l.shift }
      res == 0
    end
    module_function :secure_compare

    def variable_size_secure_compare(a, b)
      secure_compare(::Digest::SHA256.hexdigest(a), ::Digest::SHA256.hexdigest(b))
    end
    module_function :variable_size_secure_compare
  end
end

module ActionController
  class Base
    def self.http_basic_authenticate_with(options = {})
      before_action(options.except(:name, :password, :realm)) do
        authenticate_or_request_with_http_basic(options[:realm] || "Application") do |name, password|
          # This comparison uses & so that it doesn't short circuit and
          # uses `variable_size_secure_compare` so that length information
          # isn't leaked.
          ActiveSupport::SecurityUtils.variable_size_secure_compare(name, options[:name]) &
            ActiveSupport::SecurityUtils.variable_size_secure_compare(password, options[:password])
        end
      end
    end
  end
end
```


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.

* 4-1-basic_auth.patch - Patch for 4.1 series
* 4-2-basic_auth.patch - Patch for 4.2 series
* 5-0-basic_auth.patch - Patch for 5.0 series

Please note that only the 4.1.x and 4.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
-------

Thank you to Daniel Waterworth for reporting the problem and working with us to
fix it.

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

From 9ffe46fb65dcde8670484403c827182621ac2901 Mon Sep 17 00:00:00 2001
From: Aaron Patterson <aaron.patterson@...il.com>
Date: Thu, 29 Oct 2015 10:42:44 -0700
Subject: [PATCH] use secure string comparisons for basic auth username /
 password

this will avoid timing attacks against applications that use basic auth.

Conflicts:
	activesupport/lib/active_support/security_utils.rb

Conflicts:
	actionpack/lib/action_controller/metal/http_authentication.rb

CVE-2015-7576
---
 .../action_controller/metal/http_authentication.rb |  7 +++++-
 activesupport/lib/active_support/security_utils.rb | 27 ++++++++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 activesupport/lib/active_support/security_utils.rb

diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index fe4ab65..2ae5160 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -1,5 +1,6 @@
 require 'active_support/base64'
 require 'active_support/core_ext/object/blank'
+require 'active_support/security_utils'
 
 module ActionController
   module HttpAuthentication
@@ -111,7 +112,11 @@ module ActionController
           def http_basic_authenticate_with(options = {})
             before_filter(options.except(:name, :password, :realm)) do
               authenticate_or_request_with_http_basic(options[:realm] || "Application") do |name, password|
-                name == options[:name] && password == options[:password]
+                # This comparison uses & so that it doesn't short circuit and
+                # uses `variable_size_secure_compare` so that length information
+                # isn't leaked.
+                ActiveSupport::SecurityUtils.variable_size_secure_compare(name, options[:name]) &
+                  ActiveSupport::SecurityUtils.variable_size_secure_compare(password, options[:password])
               end
             end
           end
diff --git a/activesupport/lib/active_support/security_utils.rb b/activesupport/lib/active_support/security_utils.rb
new file mode 100644
index 0000000..9be8613
--- /dev/null
+++ b/activesupport/lib/active_support/security_utils.rb
@@ -0,0 +1,27 @@
+require 'digest'
+
+module ActiveSupport
+  module SecurityUtils
+    # Constant time string comparison.
+    #
+    # The values compared should be of fixed length, such as strings
+    # that have already been processed by HMAC. This should not be used
+    # on variable length plaintext strings because it could leak length info
+    # via timing attacks.
+    def secure_compare(a, b)
+      return false unless a.bytesize == b.bytesize
+
+      l = a.unpack "C#{a.bytesize}"
+
+      res = 0
+      b.each_byte { |byte| res |= byte ^ l.shift }
+      res == 0
+    end
+    module_function :secure_compare
+
+    def variable_size_secure_compare(a, b) # :nodoc:
+      secure_compare(::Digest::SHA256.hexdigest(a), ::Digest::SHA256.hexdigest(b))
+    end
+    module_function :variable_size_secure_compare
+  end
+end
-- 
2.2.1


From 0de876c53fe9355f1e9a73e923519f2a2241f527 Mon Sep 17 00:00:00 2001
From: Aaron Patterson <aaron.patterson@...il.com>
Date: Thu, 29 Oct 2015 10:42:44 -0700
Subject: [PATCH] use secure string comparisons for basic auth username /
 password

this will avoid timing attacks against applications that use basic auth.

Conflicts:
	activesupport/lib/active_support/security_utils.rb

CVE-2015-7576
---
 .../action_controller/metal/http_authentication.rb |  7 +++++-
 activesupport/lib/active_support/security_utils.rb | 27 ++++++++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 activesupport/lib/active_support/security_utils.rb

diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 167df2f..db93e20 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -1,4 +1,5 @@
 require 'base64'
+require 'active_support/security_utils'
 
 module ActionController
   # Makes it dead easy to do HTTP Basic, Digest and Token authentication.
@@ -70,7 +71,11 @@ module ActionController
           def http_basic_authenticate_with(options = {})
             before_action(options.except(:name, :password, :realm)) do
               authenticate_or_request_with_http_basic(options[:realm] || "Application") do |name, password|
-                name == options[:name] && password == options[:password]
+                # This comparison uses & so that it doesn't short circuit and
+                # uses `variable_size_secure_compare` so that length information
+                # isn't leaked.
+                ActiveSupport::SecurityUtils.variable_size_secure_compare(name, options[:name]) &
+                  ActiveSupport::SecurityUtils.variable_size_secure_compare(password, options[:password])
               end
             end
           end
diff --git a/activesupport/lib/active_support/security_utils.rb b/activesupport/lib/active_support/security_utils.rb
new file mode 100644
index 0000000..bb22125
--- /dev/null
+++ b/activesupport/lib/active_support/security_utils.rb
@@ -0,0 +1,27 @@
+require 'digest'
+
+module ActiveSupport
+  module SecurityUtils
+    # Constant time string comparison.
+    #
+    # The values compared should be of fixed length, such as strings
+    # that have already been processed by HMAC. This should not be used
+    # on variable length plaintext strings because it could leak length info
+    # via timing attacks.
+    def secure_compare(a, b)
+      return false unless a.bytesize == b.bytesize
+
+      l = a.unpack "C#{a.bytesize}"
+
+      res = 0
+      b.each_byte { |byte| res |= byte ^ l.shift }
+      res == 0
+    end
+    module_function :secure_compare
+
+    def variable_size_secure_compare(a, b) # :nodoc:
+      secure_compare(::Digest::SHA256.hexdigest(a), ::Digest::SHA256.hexdigest(b))
+    end
+    module_function :variable_size_secure_compare
+  end
+end
-- 
2.2.1


From 53b153b90fc2400a8568cf4aa5017c612bf62401 Mon Sep 17 00:00:00 2001
From: Aaron Patterson <aaron.patterson@...il.com>
Date: Thu, 29 Oct 2015 10:42:44 -0700
Subject: [PATCH] use secure string comparisons for basic auth username /
 password

this will avoid timing attacks against applications that use basic auth.

CVE-2015-7576
---
 actionpack/lib/action_controller/metal/http_authentication.rb | 7 ++++++-
 activesupport/lib/active_support/security_utils.rb            | 7 +++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index a219d35..2777d0f 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -1,4 +1,5 @@
 require 'base64'
+require 'active_support/security_utils'
 
 module ActionController
   # Makes it dead easy to do HTTP Basic, Digest and Token authentication.
@@ -68,7 +69,11 @@ module ActionController
           def http_basic_authenticate_with(options = {})
             before_action(options.except(:name, :password, :realm)) do
               authenticate_or_request_with_http_basic(options[:realm] || "Application") do |name, password|
-                name == options[:name] && password == options[:password]
+                # This comparison uses & so that it doesn't short circuit and
+                # uses `variable_size_secure_compare` so that length information
+                # isn't leaked.
+                ActiveSupport::SecurityUtils.variable_size_secure_compare(name, options[:name]) &
+                  ActiveSupport::SecurityUtils.variable_size_secure_compare(password, options[:password])
               end
             end
           end
diff --git a/activesupport/lib/active_support/security_utils.rb b/activesupport/lib/active_support/security_utils.rb
index 64c4801..bb22125 100644
--- a/activesupport/lib/active_support/security_utils.rb
+++ b/activesupport/lib/active_support/security_utils.rb
@@ -1,3 +1,5 @@
+require 'digest'
+
 module ActiveSupport
   module SecurityUtils
     # Constant time string comparison.
@@ -16,5 +18,10 @@ module ActiveSupport
       res == 0
     end
     module_function :secure_compare
+
+    def variable_size_secure_compare(a, b) # :nodoc:
+      secure_compare(::Digest::SHA256.hexdigest(a), ::Digest::SHA256.hexdigest(b))
+    end
+    module_function :variable_size_secure_compare
   end
 end
-- 
2.2.1


From b0b42de5f04100e9672170898cb94584309fdc39 Mon Sep 17 00:00:00 2001
From: Aaron Patterson <aaron.patterson@...il.com>
Date: Thu, 29 Oct 2015 10:42:44 -0700
Subject: [PATCH] use secure string comparisons for basic auth username /
 password

this will avoid timing attacks against applications that use basic auth.

CVE-2015-7576
---
 actionpack/lib/action_controller/metal/http_authentication.rb | 7 ++++++-
 activesupport/lib/active_support/security_utils.rb            | 7 +++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 2ac6e37..35be6d9 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -1,4 +1,5 @@
 require 'base64'
+require 'active_support/security_utils'
 
 module ActionController
   # Makes it dead easy to do HTTP Basic, Digest and Token authentication.
@@ -68,7 +69,11 @@ module ActionController
           def http_basic_authenticate_with(options = {})
             before_action(options.except(:name, :password, :realm)) do
               authenticate_or_request_with_http_basic(options[:realm] || "Application") do |name, password|
-                name == options[:name] && password == options[:password]
+                # This comparison uses & so that it doesn't short circuit and
+                # uses `variable_size_secure_compare` so that length information
+                # isn't leaked.
+                ActiveSupport::SecurityUtils.variable_size_secure_compare(name, options[:name]) &
+                  ActiveSupport::SecurityUtils.variable_size_secure_compare(password, options[:password])
               end
             end
           end
diff --git a/activesupport/lib/active_support/security_utils.rb b/activesupport/lib/active_support/security_utils.rb
index 64c4801..9be8613 100644
--- a/activesupport/lib/active_support/security_utils.rb
+++ b/activesupport/lib/active_support/security_utils.rb
@@ -1,3 +1,5 @@
+require 'digest'
+
 module ActiveSupport
   module SecurityUtils
     # Constant time string comparison.
@@ -16,5 +18,10 @@ module ActiveSupport
       res == 0
     end
     module_function :secure_compare
+
+    def variable_size_secure_compare(a, b) # :nodoc:
+      secure_compare(::Digest::SHA256.hexdigest(a), ::Digest::SHA256.hexdigest(b))
+    end
+    module_function :variable_size_secure_compare
   end
 end
-- 
2.2.1



[ CONTENT OF TYPE application/pgp-signature SKIPPED ]

Powered by blists - more mailing lists

Your e-mail address:

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Powered by Openwall GNU/*/Linux - Powered by OpenVZ