Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock
Dear release team, Please unblock package ruby-rack, which fixes grave security bugs: #698440 #700173 #700226 3 BTS contains 5 CVE adviseries tracked as: https://security-tracker.debian.org/tracker/source-package/ruby-rack All patches are backported from upstream fix. I've prepared nmu with maintainer's permission, and debdiff is below: (or, staging at mentors at: http://mentors.debian.net/debian/pool/main/r/ruby-rack/ruby-rack_1.4.1-2.1.dsc ) I'll ask for upload sponsor after this request would be approved. diff -Nru ruby-rack-1.4.1/debian/changelog ruby-rack-1.4.1/debian/changelog --- ruby-rack-1.4.1/debian/changelog 2012-06-26 03:07:51.000000000 +0900 +++ ruby-rack-1.4.1/debian/changelog 2013-02-20 21:21:25.000000000 +0900 @@ -1,3 +1,19 @@ +ruby-rack (1.4.1-2.1) testing-security; urgency=high + + [ KURASHIKI Satoru ] + * Non-maintainer upload. + * Create cherry-picked patches for Security Fix (Closes: #700173 #700226). + - CVE-2013-0262: 0004-Prevent-symlink-path-traversals.patch + - CVE-2013-0263: 0005-Use-secure_compare-for-hmac-comparison.patch + + [ Youhei SASAKI ] + * Create cherry-picked patches for Security Fix (Closes: #698440). + - CVE-2012-6109: 0001-Fix-parsing-performance-for-unquoted-filenames.patch + - CVE-2013-0183: 0002-multipart-parser-avoid-unbounded-gets-method.patch + - CVE-2013-0184: 0003-Reimplement-auth-scheme-fix.patch + + -- KURASHIKI Satoru <lur...@gmail.com> Wed, 20 Feb 2013 20:56:31 +0900 + ruby-rack (1.4.1-2) unstable; urgency=low * Bump build dependency on gem2deb to >= 0.3.0~ diff -Nru ruby-rack-1.4.1/debian/patches/0001-Fix-parsing-performance-for-unquoted-filenames.patch ruby-rack-1.4.1/debian/patches/0001-Fix-parsing-performance-for-unquoted-filenames.patch --- ruby-rack-1.4.1/debian/patches/0001-Fix-parsing-performance-for-unquoted-filenames.patch 1970-01-01 09:00:00.000000000 +0900 +++ ruby-rack-1.4.1/debian/patches/0001-Fix-parsing-performance-for-unquoted-filenames.patch 2013-02-10 23:07:16.000000000 +0900 @@ -0,0 +1,67 @@ +From: James Tucker <jftuc...@gmail.com> +Date: Sun, 13 May 2012 15:02:17 -0700 +Subject: Fix parsing performance for unquoted filenames + +Special thanks to Paul Rogers & Eric Wong + +Origin: upstream, https://github.com/rack/rack/commit/4fc44671b3cad569421f4f8b775c0590b86f575e +Bug: https://security-tracker.debian.org/tracker/CVE-2012-6109 +Bug-Debian: http://bugs.debian.org/698440 + +--- + lib/rack/multipart.rb | 4 ++-- + test/spec_multipart.rb | 21 +++++++++++++++++++++ + 2 files changed, 23 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 Rack + 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 @@ module Rack + end + + end +-end +\ No newline at end of file ++end +diff --git a/test/spec_multipart.rb b/test/spec_multipart.rb +index b0bf57c..e4e5981 100644 +--- a/test/spec_multipart.rb ++++ b/test/spec_multipart.rb +@@ -48,6 +48,27 @@ describe Rack::Multipart do + params['profile']['bio'].should.include 'hello' + 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 ++ + should "parse multipart upload with text file" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:text)) + params = Rack::Multipart.parse_multipart(env) diff -Nru ruby-rack-1.4.1/debian/patches/0002-multipart-parser-avoid-unbounded-gets-method.patch ruby-rack-1.4.1/debian/patches/0002-multipart-parser-avoid-unbounded-gets-method.patch --- ruby-rack-1.4.1/debian/patches/0002-multipart-parser-avoid-unbounded-gets-method.patch 1970-01-01 09:00:00.000000000 +0900 +++ ruby-rack-1.4.1/debian/patches/0002-multipart-parser-avoid-unbounded-gets-method.patch 2013-02-10 23:07:16.000000000 +0900 @@ -0,0 +1,104 @@ +From: Eric Wong <normalper...@yhbt.net> +Date: Wed, 22 Aug 2012 22:48:23 +0000 +Subject: multipart/parser: avoid unbounded #gets method + +Malicious clients may send excessively long lines +to trigger out-of-memory errors in a Rack web server. + +Origin: upstream, https://github.com/rack/rack/commit/f95113402b7239f225282806673e1b6424522b18 +Bug: https://security-tracker.debian.org/tracker/CVE-2013-0183 +Bug-Debian: http://bugs.debian.org/698440 + +--- + 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 98eceaa..3773de7 100644 +--- a/lib/rack/multipart/parser.rb ++++ b/lib/rack/multipart/parser.rb +@@ -68,9 +68,16 @@ module Rack + + 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 e4e5981..1c50d9a 100644 +--- a/test/spec_multipart.rb ++++ b/test/spec_multipart.rb +@@ -69,6 +69,59 @@ contents\r + params["file"][:filename].should.equal('long' * 100) + 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) diff -Nru ruby-rack-1.4.1/debian/patches/0003-Reimplement-auth-scheme-fix.patch ruby-rack-1.4.1/debian/patches/0003-Reimplement-auth-scheme-fix.patch --- ruby-rack-1.4.1/debian/patches/0003-Reimplement-auth-scheme-fix.patch 1970-01-01 09:00:00.000000000 +0900 +++ ruby-rack-1.4.1/debian/patches/0003-Reimplement-auth-scheme-fix.patch 2013-02-11 11:20:43.000000000 +0900 @@ -0,0 +1,131 @@ +From: James Tucker <jftuc...@gmail.com> +Date: Sun, 13 Jan 2013 13:10:20 -0800 +Subject: 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 + +Origin: upstream, https://github.com/rack/rack/commit/87df8796a6e4555ec8fd3817c419c6b44b7ca459 +Bug: https://security-tracker.debian.org/tracker/CVE-2013-0184 +Bug-Debian: http://bugs.debian.org/698440 + +--- + 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 Rack + 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 @@ module Rack + 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 diff -Nru ruby-rack-1.4.1/debian/patches/0004-Prevent-symlink-path-traversals.patch ruby-rack-1.4.1/debian/patches/0004-Prevent-symlink-path-traversals.patch --- ruby-rack-1.4.1/debian/patches/0004-Prevent-symlink-path-traversals.patch 1970-01-01 09:00:00.000000000 +0900 +++ ruby-rack-1.4.1/debian/patches/0004-Prevent-symlink-path-traversals.patch 2013-02-20 21:41:42.000000000 +0900 @@ -0,0 +1,40 @@ +Description: Prevent symlink path traversals + rack/file.rb (Rack::File) in Rack 1.5.x before 1.5.2 and 1.4.x before 1.4.5 + allows attackers to access arbitrary files outside the intended root + directory via a crafted PATH_INFO environment variable, probably a directory + traversal vulnerability that is remotely exploitable, aka "symlink path traversals." + +Origin: upstream, https://github.com/rack/rack/commit/6f237e4c9fab649d3750482514f0fde76c56ab30 +Bug: https://security-tracker.debian.org/tracker/CVE-2013-0262 +Bug-Debian: http://bugs.debian.org/700173 + +Index: ruby-rack/lib/rack/file.rb +=================================================================== +--- ruby-rack.orig/lib/rack/file.rb 2013-02-20 21:36:40.000000000 +0900 ++++ ruby-rack/lib/rack/file.rb 2013-02-20 21:39:58.265999186 +0900 +@@ -40,19 +40,14 @@ + @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(404, "Not Found") 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 -Nru ruby-rack-1.4.1/debian/patches/0005-Use-secure_compare-for-hmac-comparison.patch ruby-rack-1.4.1/debian/patches/0005-Use-secure_compare-for-hmac-comparison.patch --- ruby-rack-1.4.1/debian/patches/0005-Use-secure_compare-for-hmac-comparison.patch 1970-01-01 09:00:00.000000000 +0900 +++ ruby-rack-1.4.1/debian/patches/0005-Use-secure_compare-for-hmac-comparison.patch 2013-02-20 23:15:59.000000000 +0900 @@ -0,0 +1,65 @@ +Description: Use secure compare for hmac comparison + Rack::Session::Cookie in Rack 1.5.x before 1.5.2, 1.4.x before 1.4.5, + 1.3.x before 1.3.10, 1.2.x before 1.2.8, and 1.1.x before 1.1.6 allows + remote attackers to guess the session cookie, gain privileges, and + execute arbitrary code via a timing attack involving am HMAC + comparison function that does not run in constant time. + +Origin: upstream, + https://github.com/rack/rack/commit/0cd7e9aa397f8ebb3b8481d67dbac8b4863a7f07, + https://github.com/rack/rack/commit/9a81b961457805f6d1a5c275d053068440421e11 +Bug: https://security-tracker.debian.org/tracker/CVE-2013-0263 +Bug-Debian: http://bugs.debian.org/700226 + +Index: ruby-rack/lib/rack/session/cookie.rb +=================================================================== +--- ruby-rack.orig/lib/rack/session/cookie.rb 2013-02-11 15:09:25.000000000 +0900 ++++ ruby-rack/lib/rack/session/cookie.rb 2013-02-20 23:11:19.091085974 +0900 +@@ -108,7 +108,7 @@ + + if session_data && digest + ok = @secrets.any? do |secret| +- secret && digest == generate_hmac(session_data, secret) ++ secret && Rack::Utils.secure_compare(digest, generate_hmac(session_data, secret)) + end + end + +Index: ruby-rack/lib/rack/utils.rb +=================================================================== +--- ruby-rack.orig/lib/rack/utils.rb 2013-02-11 15:09:25.000000000 +0900 ++++ ruby-rack/lib/rack/utils.rb 2013-02-20 23:12:39.171087876 +0900 +@@ -336,6 +336,18 @@ + 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 +Index: ruby-rack/test/spec_utils.rb +=================================================================== +--- ruby-rack.orig/test/spec_utils.rb 2013-02-11 15:09:25.000000000 +0900 ++++ ruby-rack/test/spec_utils.rb 2013-02-20 23:13:55.627089693 +0900 +@@ -322,6 +322,11 @@ + 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 -Nru ruby-rack-1.4.1/debian/patches/series ruby-rack-1.4.1/debian/patches/series --- ruby-rack-1.4.1/debian/patches/series 1970-01-01 09:00:00.000000000 +0900 +++ ruby-rack-1.4.1/debian/patches/series 2013-02-21 21:10:07.000000000 +0900 @@ -0,0 +1,5 @@ +0001-Fix-parsing-performance-for-unquoted-filenames.patch +0002-multipart-parser-avoid-unbounded-gets-method.patch +0003-Reimplement-auth-scheme-fix.patch +0004-Prevent-symlink-path-traversals.patch +0005-Use-secure_compare-for-hmac-comparison.patch unblock ruby-rack/1.4.1-2.1 -- System Information: Debian Release: 7.0 APT prefers unstable APT policy: (500, 'unstable'), (500, 'testing') Architecture: amd64 (x86_64) Kernel: Linux 3.2.0-4-amd64 (SMP w/4 CPU cores) Locale: LANG=ja_JP.UTF-8, LC_CTYPE=ja_JP.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash -- To UNSUBSCRIBE, email to debian-release-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/20130221143142.24315.29364.report...@dandelion.in.yoikaze.org