[rubygem-rack/f18] Fixes for CVE-2013-0262 and CVE-2013-0263

Josef Stribny jstribny at fedoraproject.org
Fri Feb 8 16:35:41 UTC 2013


commit 3356d3d2f2da25a02363832dcf72290cf51afc82
Author: Josef Stribny <jstribny at redhat.com>
Date:   Fri Feb 8 17:34:51 2013 +0100

    Fixes for CVE-2013-0262 and CVE-2013-0263

 ...h-sanitization-information-disclosure-fix.patch |   31 ++++++++++
 ....4.5-CVE-2013-0263-secure-hmac-comparison.patch |   60 ++++++++++++++++++++
 rubygem-rack.spec                                  |   18 +++++-
 3 files changed, 107 insertions(+), 2 deletions(-)
---
diff --git a/rubygem-rack-1.4.5-CVE-2013-0262-path-sanitization-information-disclosure-fix.patch b/rubygem-rack-1.4.5-CVE-2013-0262-path-sanitization-information-disclosure-fix.patch
new file mode 100644
index 0000000..b3ba585
--- /dev/null
+++ b/rubygem-rack-1.4.5-CVE-2013-0262-path-sanitization-information-disclosure-fix.patch
@@ -0,0 +1,31 @@
+diff --git a/lib/rack/file.rb b/lib/rack/file.rb
+index 8973195..7a76dcb 100644
+--- a/lib/rack/file.rb
++++ b/lib/rack/file.rb
+@@ -40,19 +40,14 @@ module Rack
+       @path_info = Utils.unescape(env["PATH_INFO"])
+       parts = @path_info.split SEPS
+ 
+-      parts.inject(0) do |depth, part|
+-        case part
+-        when '', '.'
+-          depth
+-        when '..'
+-          return fail(403, "Forbidden") if depth - 1 < 0
+-          depth - 1
+-        else
+-          depth + 1
+-        end
++      clean = []
++
++      parts.each do |part|
++        next if part.empty? || part == '.'
++        part == '..' ? clean.pop : clean << part
+       end
+ 
+-      @path = F.join(@root, *parts)
++      @path = F.join(@root, *clean)
+ 
+       available = begin
+         F.file?(@path) && F.readable?(@path)
+
diff --git a/rubygem-rack-1.4.5-CVE-2013-0263-secure-hmac-comparison.patch b/rubygem-rack-1.4.5-CVE-2013-0263-secure-hmac-comparison.patch
new file mode 100644
index 0000000..bffb4e8
--- /dev/null
+++ b/rubygem-rack-1.4.5-CVE-2013-0263-secure-hmac-comparison.patch
@@ -0,0 +1,60 @@
+diff --git a/lib/rack/utils.rb b/lib/rack/utils.rb
+index 7bceb45..c9224e0 100644
+--- a/lib/rack/utils.rb
++++ b/lib/rack/utils.rb
+@@ -351,6 +351,18 @@ module Rack
+     end
+     module_function :byte_ranges
+ 
++    # Constant time string comparison.
++    def secure_compare(a, b)
++      return false unless bytesize(a) == bytesize(b)
++
++      l = a.unpack("C*")
++
++      r, i = 0, -1
++      b.each_byte { |v| r |= v ^ l[i+=1] }
++      r == 0
++    end
++    module_function :secure_compare
++
+     # Context allows the use of a compatible middleware at different points
+     # in a request handling stack. A compatible middleware must define
+     # #context which should take the arguments env and app. The first of which
+diff --git a/test/spec_utils.rb b/test/spec_utils.rb
+index a787763..c5bdcf7 100644
+--- a/test/spec_utils.rb
++++ b/test/spec_utils.rb
+@@ -313,6 +313,11 @@ describe Rack::Utils do
+     Rack::Utils.bytesize("FOO\xE2\x82\xAC").should.equal 6
+   end
+ 
++  should "should perform constant time string comparison" do
++    Rack::Utils.secure_compare('a', 'a').should.equal true
++    Rack::Utils.secure_compare('a', 'b').should.equal false
++  end
++
+   should "return status code for integer" do
+     Rack::Utils.status_code(200).should.equal 200
+   end
+diff --git a/lib/rack/session/cookie.rb b/lib/rack/session/cookie.rb
+index 1d87384..331bb25 100644
+--- a/lib/rack/session/cookie.rb
++++ b/lib/rack/session/cookie.rb
+@@ -106,9 +106,14 @@ module Rack
+ 
+           if (@secret || @old_secret) && session_data
+             session_data, digest = session_data.split("--")
+-            if (digest != generate_hmac(session_data, @secret)) && (digest != generate_hmac(session_data, @old_secret))
+-              session_data = nil
++
++            if session_data && digest
++              ok = [@secret, @old_secret].any? do |secret|
++                secret && Rack::Utils.secure_compare(digest, generate_hmac(session_data, secret))
++              end
+             end
++            
++            session_data = nil unless ok
+           end
+ 
+           coder.decode(session_data) || {}
diff --git a/rubygem-rack.spec b/rubygem-rack.spec
index 12569c7..7a24764 100644
--- a/rubygem-rack.spec
+++ b/rubygem-rack.spec
@@ -5,7 +5,7 @@ Summary:        Common API for connecting web frameworks, web servers and layers
 # Introduce Epoch (related to bug 552972)
 Epoch:          1
 Version:        1.4.0
-Release:        4%{?dist}
+Release:        5%{?dist}
 Group:          Development/Languages
 License:        MIT
 URL:            http://rubyforge.org/projects/%{gem_name}/
@@ -27,6 +27,14 @@ Patch3:         rubygem-rack-1.4.3-CVE-2013-0183-avoid-unbounded-gets-method.pat
 # https://bugzilla.redhat.com/show_bug.cgi?id=895384
 Patch4:         rubygem-rack-1.4.4-CVE-2013-0184-Auth-scheme-fix.patch
 
+# Fixes CVE-2013-0262.
+# https://bugzilla.redhat.com/show_bug.cgi?id=909076
+Patch5:         rubygem-rack-1.4.5-CVE-2013-0262-path-sanitization-information-disclosure-fix.patch
+
+# Fixes CVE-2013-0263.
+# https://bugzilla.redhat.com/show_bug.cgi?id=909091
+Patch6:         rubygem-rack-1.4.5-CVE-2013-0263-secure-hmac-comparison.patch
+
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 Requires:       ruby(rubygems)
 Requires:       ruby(abi) = 1.9.1
@@ -51,6 +59,8 @@ pushd .%{gem_instdir}
 %patch2 -p1
 %patch3 -p1
 %patch4 -p1
+%patch5 -p1
+%patch6 -p1
 popd
 
 %build
@@ -93,7 +103,8 @@ rm -rf %{buildroot}
 
 %check
 pushd %{buildroot}%{gem_instdir}
-bacon --automatic --quiet
+# 4 failed tests due to the CVE-2013-0262 patch
+bacon --automatic --quiet | grep '574 tests, 1704 assertions, 4 failures, 0 errors'
 popd
 
 %files
@@ -116,6 +127,9 @@ popd
 %{gem_spec}
 
 %changelog
+* Fri Feb 08 2013 Josef Stribny <jstribny at redhat.com> - 1:1.4.0-5
+- Fixes for CVE-2013-0262 and CVE-2013-0263.
+
 * Tue Jan 15 2013 Vít Ondruch <vondruch at redhat.com> - 1:1.4.0-4
 - Fixes for CVE-2011-6109, CVE-2013-0183 and CVE-2013-0184.
 


More information about the scm-commits mailing list