[rubygem-rack/f16] Fixes for CVE-2011-6109, CVE-2013-0183 and CVE-2013-0184.

Vít Ondruch vondruch at fedoraproject.org
Tue Jan 15 15:30:10 UTC 2013


commit 95b406c64493dbf3cd345a0e2ba359e84ed9d91e
Author: Vít Ondruch <vondruch at redhat.com>
Date:   Tue Jan 15 15:13:32 2013 +0100

    Fixes for CVE-2011-6109, CVE-2013-0183 and CVE-2013-0184.

 ...arsing-performance-for-unquoted-filenames.patch |   67 ++++++++++
 ...CVE-2013-0183-avoid-unbounded-gets-method.patch |  103 ++++++++++++++++
 ...-rack-1.4.4-CVE-2013-0184-Auth-scheme-fix.patch |  130 ++++++++++++++++++++
 rubygem-rack.spec                                  |   21 +++-
 4 files changed, 320 insertions(+), 1 deletions(-)
---
diff --git a/rubygem-rack-1.4.2-CVE-2012-6109-Fix-parsing-performance-for-unquoted-filenames.patch b/rubygem-rack-1.4.2-CVE-2012-6109-Fix-parsing-performance-for-unquoted-filenames.patch
new file mode 100644
index 0000000..3c5d615
--- /dev/null
+++ b/rubygem-rack-1.4.2-CVE-2012-6109-Fix-parsing-performance-for-unquoted-filenames.patch
@@ -0,0 +1,67 @@
+From 4fc44671b3cad569421f4f8b775c0590b86f575e Mon Sep 17 00:00:00 2001
+From: James Tucker <jftucker at gmail.com>
+Date: Sun, 13 May 2012 15:02:17 -0700
+Subject: [PATCH] Fix parsing performance for unquoted filenames
+
+Special thanks to Paul Rogers & Eric Wong
+
+Conflicts:
+	test/spec_multipart.rb
+---
+ lib/rack/multipart.rb  |    4 ++--
+ test/spec_multipart.rb |   22 ++++++++++++++++++++++
+ 2 files changed, 24 insertions(+), 2 deletions(-)
+
+diff --git a/lib/rack/multipart.rb b/lib/rack/multipart.rb
+index 3777106..6849248 100644
+--- a/lib/rack/multipart.rb
++++ b/lib/rack/multipart.rb
+@@ -12,7 +12,7 @@ module Multipart
+     MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
+     TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/
+     CONDISP = /Content-Disposition:\s*#{TOKEN}\s*/i
+-    DISPPARM = /;\s*(#{TOKEN})=("(?:\\"|[^"])*"|#{TOKEN})*/
++    DISPPARM = /;\s*(#{TOKEN})=("(?:\\"|[^"])*"|#{TOKEN})/
+     RFC2183 = /^#{CONDISP}(#{DISPPARM})+$/i
+     BROKEN_QUOTED = /^#{CONDISP}.*;\sfilename="(.*?)"(?:\s*$|\s*;\s*#{TOKEN}=)/i
+     BROKEN_UNQUOTED = /^#{CONDISP}.*;\sfilename=(#{TOKEN})/i
+@@ -31,4 +31,4 @@ def build_multipart(params, first = true)
+     end
+ 
+   end
+-end
+\ No newline at end of file
++end
+diff --git a/test/spec_multipart.rb b/test/spec_multipart.rb
+index 38c0d28..88729ee 100644
+--- a/test/spec_multipart.rb
++++ b/test/spec_multipart.rb
+@@ -295,4 +295,25 @@ def multipart_file(name)
+       message.should.equal "value must be a Hash"
+   end
+ 
++  should "parse very long unquoted multipart file names" do
++    data = <<-EOF
++--AaB03x\r
++Content-Type: text/plain\r
++Content-Disposition: attachment; name=file; filename=#{'long' * 100}\r
++\r
++contents\r
++--AaB03x--\r
++    EOF
++
++    options = {
++      "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
++      "CONTENT_LENGTH" => data.length.to_s,
++      :input => StringIO.new(data)
++    }
++    env = Rack::MockRequest.env_for("/", options)
++    params = Rack::Utils::Multipart.parse_multipart(env)
++
++    params["file"][:filename].should.equal('long' * 100)
++  end
++
+ end
+-- 
+1.7.10
+
diff --git a/rubygem-rack-1.4.3-CVE-2013-0183-avoid-unbounded-gets-method.patch b/rubygem-rack-1.4.3-CVE-2013-0183-avoid-unbounded-gets-method.patch
new file mode 100644
index 0000000..a6187ac
--- /dev/null
+++ b/rubygem-rack-1.4.3-CVE-2013-0183-avoid-unbounded-gets-method.patch
@@ -0,0 +1,103 @@
+From f95113402b7239f225282806673e1b6424522b18 Mon Sep 17 00:00:00 2001
+From: Eric Wong <normalperson at yhbt.net>
+Date: Wed, 22 Aug 2012 22:48:23 +0000
+Subject: [PATCH] multipart/parser: avoid unbounded #gets method
+
+Malicious clients may send excessively long lines
+to trigger out-of-memory errors in a Rack web server.
+---
+ lib/rack/multipart/parser.rb |   13 ++++++++---
+ test/spec_multipart.rb       |   53 ++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 63 insertions(+), 3 deletions(-)
+
+diff --git a/lib/rack/multipart/parser.rb b/lib/rack/multipart/parser.rb
+index 21986cc..1315c7b 100644
+--- a/lib/rack/multipart/parser.rb
++++ b/lib/rack/multipart/parser.rb
+@@ -70,9 +70,16 @@ def rx
+ 
+       def fast_forward_to_first_boundary
+         loop do
+-          read_buffer = @io.gets
+-          break if read_buffer == full_boundary
+-          raise EOFError, "bad content body" if read_buffer.nil?
++          content = @io.read(BUFSIZE)
++          raise EOFError, "bad content body" unless content
++          @buf << content
++
++          while @buf.gsub!(/\A([^\n]*\n)/, '')
++            read_buffer = $1
++            return if read_buffer == full_boundary
++          end
++
++          raise EOFError, "bad content body" if Utils.bytesize(@buf) >= BUFSIZE
+         end
+       end
+ 
+diff --git a/test/spec_multipart.rb b/test/spec_multipart.rb
+index 88729ee..ca3f974 100644
+--- a/test/spec_multipart.rb
++++ b/test/spec_multipart.rb
+@@ -48,6 +48,59 @@ def multipart_file(name)
+     params['profile']['bio'].should.include 'hello'
+   end
+ 
++  should "reject insanely long boundaries" do
++    # using a pipe since a tempfile can use up too much space
++    rd, wr = IO.pipe
++
++    # we only call rewind once at start, so make sure it succeeds
++    # and doesn't hit ESPIPE
++    def rd.rewind; end
++    wr.sync = true
++
++    # mock out length to make this pipe look like a Tempfile
++    def rd.length
++      1024 * 1024 * 8
++    end
++
++    # write to a pipe in a background thread, this will write a lot
++    # unless Rack (properly) shuts down the read end
++    thr = Thread.new do
++      begin
++        wr.write("--AaB03x")
++
++        # make the initial boundary a few gigs long
++        longer = "0123456789" * 1024 * 1024
++        (1024 * 1024).times { wr.write(longer) }
++
++        wr.write("\r\n")
++        wr.write('Content-Disposition: form-data; name="a"; filename="a.txt"')
++        wr.write("\r\n")
++        wr.write("Content-Type: text/plain\r\n")
++        wr.write("\r\na")
++        wr.write("--AaB03x--\r\n")
++        wr.close
++      rescue => err # this is EPIPE if Rack shuts us down
++        err
++      end
++    end
++
++    fixture = {
++      "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
++      "CONTENT_LENGTH" => rd.length.to_s,
++      :input => rd,
++    }
++
++    env = Rack::MockRequest.env_for '/', fixture
++    lambda {
++      Rack::Multipart.parse_multipart(env)
++    }.should.raise(EOFError)
++    rd.close
++
++    err = thr.value
++    err.should.be.instance_of Errno::EPIPE
++    wr.close
++  end
++
+   should "parse multipart upload with text file" do
+     env = Rack::MockRequest.env_for("/", multipart_fixture(:text))
+     params = Rack::Multipart.parse_multipart(env)
+-- 
+1.7.10
+
diff --git a/rubygem-rack-1.4.4-CVE-2013-0184-Auth-scheme-fix.patch b/rubygem-rack-1.4.4-CVE-2013-0184-Auth-scheme-fix.patch
new file mode 100644
index 0000000..8632b7c
--- /dev/null
+++ b/rubygem-rack-1.4.4-CVE-2013-0184-Auth-scheme-fix.patch
@@ -0,0 +1,130 @@
+From 87df8796a6e4555ec8fd3817c419c6b44b7ca459 Mon Sep 17 00:00:00 2001
+From: James Tucker <jftucker at gmail.com>
+Date: Sun, 13 Jan 2013 13:10:20 -0800
+Subject: [PATCH] Reimplement auth scheme fix
+
+ * Add Rack::Auth.add_scheme to enable folks to fix anything that breaks
+ * Add common auth schemes, MS ones, AWS ones, etc are missing, as unlikely
+ * Checked Rails - they don't use our authorization code
+ * Checked Warden - uses rails
+ * Checked Omniauth - uses rails
+ * Checked doorkeeper - users rails
+ * Checked rack-authentication - does it's own thing
+ * Checked warden-oauth - doesn't do headers
+ * Checked devise - uses rails
+ * Checked oauth2-rack - header creation only
+ * Checked rack-oauth2-server - does it's own thing
+ * Probably missed a bunch, but that'll have to do
+---
+ lib/rack.rb                       |   12 ++++++++
+ lib/rack/auth/abstract/request.rb |    6 +++-
+ test/spec_auth.rb                 |   57 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 74 insertions(+), 1 deletion(-)
+ create mode 100644 test/spec_auth.rb
+
+diff --git a/lib/rack.rb b/lib/rack.rb
+index acfcb5a..18d5097 100644
+--- a/lib/rack.rb
++++ b/lib/rack.rb
+@@ -73,6 +73,18 @@ module Digest
+       autoload :Params, "rack/auth/digest/params"
+       autoload :Request, "rack/auth/digest/request"
+     end
++
++    # Not all of the following schemes are "standards", but they are used often.
++    @schemes = %w[basic digest bearer mac token oauth oauth2]
++
++    def self.add_scheme scheme
++      @schemes << scheme
++      @schemes.uniq!
++    end
++
++    def self.schemes
++      @schemes.dup
++    end
+   end
+ 
+   module Session
+diff --git a/lib/rack/auth/abstract/request.rb b/lib/rack/auth/abstract/request.rb
+index 9e15c72..c1553bf 100644
+--- a/lib/rack/auth/abstract/request.rb
++++ b/lib/rack/auth/abstract/request.rb
+@@ -21,7 +21,11 @@ def parts
+       end
+ 
+       def scheme
+-        @scheme ||= parts.first.downcase.to_sym
++        @scheme ||=
++          begin
++            s = parts.first.downcase
++            Rack::Auth.schemes.include?(s) ? s.to_sym : s
++          end
+       end
+ 
+       def params
+diff --git a/test/spec_auth.rb b/test/spec_auth.rb
+new file mode 100644
+index 0000000..6588bd1
+--- /dev/null
++++ b/test/spec_auth.rb
+@@ -0,0 +1,57 @@
++require 'rack'
++
++describe Rack::Auth do
++  it "should have all common authentication schemes" do
++    Rack::Auth.schemes.should.include? 'basic'
++    Rack::Auth.schemes.should.include? 'digest'
++    Rack::Auth.schemes.should.include? 'bearer'
++    Rack::Auth.schemes.should.include? 'token'
++  end
++
++  it "should allow registration of new auth schemes" do
++    Rack::Auth.schemes.should.not.include "test"
++    Rack::Auth.add_scheme "test"
++    Rack::Auth.schemes.should.include "test"
++  end
++end
++
++describe Rack::Auth::AbstractRequest do
++  it "should symbolize known auth schemes" do
++    env = Rack::MockRequest.env_for('/')
++    env['HTTP_AUTHORIZATION'] = 'Basic aXJyZXNwb25zaWJsZQ=='
++    req = Rack::Auth::AbstractRequest.new(env)
++    req.scheme.should == :basic
++
++
++    env['HTTP_AUTHORIZATION'] = 'Digest aXJyZXNwb25zaWJsZQ=='
++    req = Rack::Auth::AbstractRequest.new(env)
++    req.scheme.should == :digest
++
++    env['HTTP_AUTHORIZATION'] = 'Bearer aXJyZXNwb25zaWJsZQ=='
++    req = Rack::Auth::AbstractRequest.new(env)
++    req.scheme.should == :bearer
++
++    env['HTTP_AUTHORIZATION'] = 'MAC aXJyZXNwb25zaWJsZQ=='
++    req = Rack::Auth::AbstractRequest.new(env)
++    req.scheme.should == :mac
++
++    env['HTTP_AUTHORIZATION'] = 'Token aXJyZXNwb25zaWJsZQ=='
++    req = Rack::Auth::AbstractRequest.new(env)
++    req.scheme.should == :token
++
++    env['HTTP_AUTHORIZATION'] = 'OAuth aXJyZXNwb25zaWJsZQ=='
++    req = Rack::Auth::AbstractRequest.new(env)
++    req.scheme.should == :oauth
++
++    env['HTTP_AUTHORIZATION'] = 'OAuth2 aXJyZXNwb25zaWJsZQ=='
++    req = Rack::Auth::AbstractRequest.new(env)
++    req.scheme.should == :oauth2
++  end
++
++  it "should not symbolize unknown auth schemes" do
++    env = Rack::MockRequest.env_for('/')
++    env['HTTP_AUTHORIZATION'] = 'magic aXJyZXNwb25zaWJsZQ=='
++    req = Rack::Auth::AbstractRequest.new(env)
++    req.scheme.should == "magic"
++  end
++end
+-- 
+1.7.10
+
diff --git a/rubygem-rack.spec b/rubygem-rack.spec
index 936d246..f5b14f8 100644
--- a/rubygem-rack.spec
+++ b/rubygem-rack.spec
@@ -7,7 +7,7 @@ Summary:        Common API for connecting web frameworks, web servers and layers
 # Introduce Epoch (related to bug 552972)
 Epoch:          1
 Version:        1.3.0
-Release:        2%{?dist}
+Release:        3%{?dist}
 Group:          Development/Languages
 License:        MIT
 URL:            http://rubyforge.org/projects/%{gemname}/
@@ -18,6 +18,19 @@ Patch0:         rubygem-rack-%{version}-test-object-which-responds-to-each.patch
 Patch1:         rubygem-rack-%{version}-tests-now-accept-different-query-orders.patch
 # CVE-2011-5036
 Patch2:         rubygem-rack-%{version}-limit-the-size-of-parameter-keys.patch
+
+# Fixes CVE-2012-6109.
+# https://bugzilla.redhat.com/show_bug.cgi?id=895277
+Patch3:         rubygem-rack-1.4.2-CVE-2012-6109-Fix-parsing-performance-for-unquoted-filenames.patch
+
+# Fixes CVE-2013-0183.
+# https://bugzilla.redhat.com/show_bug.cgi?id=895282
+Patch4:         rubygem-rack-1.4.3-CVE-2013-0183-avoid-unbounded-gets-method.patch
+
+# Fixes CVE-2013-0184.
+# https://bugzilla.redhat.com/show_bug.cgi?id=895384
+Patch5:         rubygem-rack-1.4.4-CVE-2013-0184-Auth-scheme-fix.patch
+
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 Requires:       rubygems
 Requires:       ruby(abi) = 1.8
@@ -40,6 +53,9 @@ pushd .%{geminstdir}
 %patch0 -p1
 %patch1 -p1
 %patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
 popd
 
 %build
@@ -105,6 +121,9 @@ popd
 %{gemdir}/specifications/%{gemname}-%{version}.gemspec
 
 %changelog
+* Tue Jan 15 2013 Vít Ondruch <vondruch at redhat.com> - 1:1.3.0-3
+- Fixes for CVE-2011-6109, CVE-2013-0183 and CVE-2013-0184.
+
 * Thu Jan 05 2012 Bohuslav Kabrda <bkabrda at redhat.com> - 1:1.3.0-2
 - Moved gem install to %%prep to be able to apply patches.
 - Applied two patches that fix test failures with Ruby 1.8.7-p357.


More information about the scm-commits mailing list