cgi_multipart_eof_fix 2.1 → 2.2

Sign up to get free protection for your applications and to get access to all the features.
File without changes
data/CHANGELOG ADDED
@@ -0,0 +1,9 @@
1
+
2
+ v2.2. don't load on Ruby > 1.8.5; copyright correction at request of Zed Shaw
3
+
4
+ v2.1. license change due to no provision for use in original Ruby license (prevents installation in Florida)
5
+
6
+ v2.0. updated for second cgi.rb vulnerability
7
+
8
+ v1.0.0. original single-patch release by Zed Shaw, et. al.
9
+
data/Manifest ADDED
@@ -0,0 +1,9 @@
1
+ test/cgi_multipart_eof_fix_test.rb
2
+ lib/rake_task_redefine_task.rb
3
+ lib/cgi_multipart_eof_fix.rb
4
+ Rakefile
5
+ RUBY-LICENSE
6
+ README
7
+ Manifest
8
+ CHANGELOG
9
+ AFL3-LICENSE
data/README ADDED
@@ -0,0 +1,41 @@
1
+
2
+ cgi_multipart_eof_fix
3
+
4
+ Fix an exploitable bug in CGI multipart parsing.
5
+
6
+ == License
7
+
8
+ Copyright 2006, 2007 Cloudburst, LLC. Portions copyright 2006 Jeremy Kemper, Jamis Buck, Zed A. Shaw, and Yukihiro Matsumoto, and used with permission. Licensed under both the AFL 3.0 and Ruby License.
9
+
10
+ == Description
11
+
12
+ Fixes an exploitable bug in CGI multipart parsing which affects Ruby <= 1.8.5. When multipart boundary attributes contain non-halting regular expression strings, the boundary searcher in the CGI module does not properly escape the parameter and will execute arbitrary regular expressions. This fix adds escaping for the user data.
13
+
14
+ This is fix is cumulative with previous CGI multipart vulnerability fixes; see version 1.0.0 of the gem by Jamis Buck et. al.
15
+
16
+ == Installation
17
+
18
+ sudo gem install cgi_multipart_eof_fix
19
+
20
+ == Scope
21
+
22
+ * Affected: standalone CGI, Mongrel, WEBrick
23
+ * Unaffected: FastCGI, Ruby 1.8.6 (all servers)
24
+ * Unknown: mod_ruby
25
+
26
+ This library will not modify versions of Ruby greater than 1.8.5.
27
+
28
+ == Usage
29
+
30
+ Run the included test to verify that the patch works as intended. Then, <tt>require</tt> the gem in every affected application, as follows:
31
+
32
+ require 'rubygems'
33
+ require 'cgi_multipart_eof_fix'
34
+
35
+ Currently Mongrel requires this gem automatically. However, Mongrel may change in the future.
36
+
37
+ == Further resources
38
+
39
+ * http://blog.evanweaver.com/pages/code#cgi_multipart_eof_fix
40
+ * http://rubyforge.org/forum/forum.php?forum_id=13985
41
+ * http://www.ruby-lang.org/en/news/2006/12/04/another-dos-vulnerability-in-cgi-library/
data/RUBY-LICENSE ADDED
@@ -0,0 +1,58 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL
3
+ (see COPYING.txt file), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) rename any non-standard executables so the names do not conflict
21
+ with standard executables, which must also be provided.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or executable
26
+ form, provided that you do at least ONE of the following:
27
+
28
+ a) distribute the executables and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard executables non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under this terms.
43
+
44
+ They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
45
+ files under the ./missing directory. See each file for the copying
46
+ condition.
47
+
48
+ 5. The scripts and library files supplied as input to or produced as
49
+ output from the software do not automatically fall under the
50
+ copyright of the software, but belong to whomever generated them,
51
+ and may be sold commercially, and may be aggregated with this
52
+ software.
53
+
54
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
55
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
56
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57
+ PURPOSE.
58
+
data/Rakefile CHANGED
@@ -1,53 +1,27 @@
1
+
1
2
  require 'rubygems'
2
3
  require 'rake'
3
-
4
- NAME = "cgi_multipart_eof_fix"
4
+ require 'lib/rake_task_redefine_task.rb'
5
5
 
6
6
  begin
7
7
  require 'rake/clean'
8
8
  require 'echoe'
9
- require 'fileutils'
10
9
 
11
- AUTHOR = "Evan Weaver"
12
- EMAIL = "evan at cloudbur dot st"
13
- DESCRIPTION = "Fix an exploitable bug in CGI multipart parsing which affects Ruby <= 1.8.5 when multipart boundary attribute contains a non-halting regular expression string."
14
- RUBYFORGE_NAME = "fauna"
15
- GEM_NAME = "cgi_multipart_eof_fix"
16
- HOMEPATH = "http://blog.evanweaver.com"
17
- RELEASE_TYPES = ["gem"]
18
- REV = nil
19
- VERS = "2.1"
20
- CLEAN.include ['**/.*.sw?', '*.gem', '.config']
21
- RDOC_OPTS = ['--quiet', '--title', "cgi_multipart_eof_fix documentation",
22
- "--opname", "index.html",
23
- "--line-numbers",
24
- "--main", "README",
25
- "--inline-source"]
26
-
27
- include FileUtils
28
- require File.join(File.dirname(__FILE__), 'lib', 'cgi_multipart_eof_fix')
29
-
30
- echoe = Echoe.new(GEM_NAME, VERS) do |p|
31
- p.author = AUTHOR
32
- p.rubyforge_name = RUBYFORGE_NAME
33
- p.name = NAME
34
- p.description = DESCRIPTION
35
- p.email = EMAIL
36
- p.summary = DESCRIPTION
37
- p.url = HOMEPATH
38
- p.test_globs = ["*_test.rb"]
39
- p.clean_globs = CLEAN
10
+ echoe = Echoe.new("cgi_multipart_eof_fix") do |p|
11
+ p.author = "Evan Weaver"
12
+ p.rubyforge_name = "fauna"
13
+ p.summary = p.description = "Fix an exploitable bug in CGI multipart parsing which affects Ruby <= 1.8.5 when multipart boundary attribute contains a non-halting regular expression string."
14
+ p.url = "http://blog.evanweaver.com/pages/code#cgi_multipart_eof_fix"
15
+ p.docs_host = "blog.evanweaver.com:~/www/snax/public/files/doc/"
16
+ p.rdoc_pattern = /CHANGELOG|LICENSE|README|lib\/cgi_multipart_eof_fix/
40
17
  end
41
18
 
42
- rescue LoadError => boom
43
- puts "You are missing a dependency required for meta-operations on this gem."
44
- puts "#{boom.to_s.capitalize}."
45
-
19
+ rescue LoadError
46
20
  desc 'Run the default tasks'
47
- task :default => :test
48
-
49
- desc 'Run the test suite.'
50
- task :test do
51
- system "ruby -Ibin:lib:test #{NAME}_test.rb"
52
- end
21
+ task :default => :test
53
22
  end
23
+
24
+ Rake::Task.redefine_task("test") do
25
+ system "ruby -Ibin:lib:test test/cgi_multipart_eof_fix_test.rb"
26
+ end
27
+
@@ -1,112 +1,123 @@
1
- require 'cgi'
2
1
 
3
- class CGI
4
- module QueryExtension
5
- def read_multipart(boundary, content_length)
6
- params = Hash.new([])
7
- boundary = "--" + boundary
8
- quoted_boundary = Regexp.quote(boundary, "n")
9
- buf = ""
10
- bufsize = 10 * 1024
11
- boundary_end=""
2
+ version = RUBY_VERSION.split(".").map {|num| num.to_i }
12
3
 
13
- # start multipart/form-data
14
- stdinput.binmode if defined? stdinput.binmode
15
- boundary_size = boundary.size + EOL.size
16
- content_length -= boundary_size
17
- status = stdinput.read(boundary_size)
18
- if nil == status
19
- raise EOFError, "no content body"
20
- elsif boundary + EOL != status
21
- raise EOFError, "bad content body #{status.inspect} expected, got #{(boundary + EOL).inspect}"
22
- end
4
+ if version[0] < 2 and version[1] < 9 and version[2] < 6
23
5
 
24
- loop do
25
- head = nil
26
- if 10240 < content_length
27
- require "tempfile"
28
- body = Tempfile.new("CGI")
29
- else
30
- begin
31
- require "stringio"
32
- body = StringIO.new
33
- rescue LoadError
6
+ $stderr.puts "** Ruby version is not up-to-date; loading cgi_multipart_eof_fix"
7
+
8
+ require 'cgi'
9
+
10
+ class CGI
11
+ module QueryExtension
12
+ def read_multipart(boundary, content_length)
13
+ params = Hash.new([])
14
+ boundary = "--" + boundary
15
+ quoted_boundary = Regexp.quote(boundary, "n")
16
+ buf = ""
17
+ bufsize = 10 * 1024
18
+ boundary_end=""
19
+
20
+ # start multipart/form-data
21
+ stdinput.binmode if defined? stdinput.binmode
22
+ boundary_size = boundary.size + EOL.size
23
+ content_length -= boundary_size
24
+ status = stdinput.read(boundary_size)
25
+ if nil == status
26
+ raise EOFError, "no content body"
27
+ elsif boundary + EOL != status
28
+ raise EOFError, "bad content body #{status.inspect} expected, got #{(boundary + EOL).inspect}"
29
+ end
30
+
31
+ loop do
32
+ head = nil
33
+ if 10240 < content_length
34
34
  require "tempfile"
35
35
  body = Tempfile.new("CGI")
36
+ else
37
+ begin
38
+ require "stringio"
39
+ body = StringIO.new
40
+ rescue LoadError
41
+ require "tempfile"
42
+ body = Tempfile.new("CGI")
43
+ end
36
44
  end
37
- end
38
- body.binmode if defined? body.binmode
39
-
40
- until head and /#{quoted_boundary}(?:#{EOL}|--)/n.match(buf)
41
-
42
- if (not head) and /#{EOL}#{EOL}/n.match(buf)
43
- buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
44
- head = $1.dup
45
- ""
45
+ body.binmode if defined? body.binmode
46
+
47
+ until head and /#{quoted_boundary}(?:#{EOL}|--)/n.match(buf)
48
+
49
+ if (not head) and /#{EOL}#{EOL}/n.match(buf)
50
+ buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
51
+ head = $1.dup
52
+ ""
53
+ end
54
+ next
55
+ end
56
+
57
+ if head and ( (EOL + boundary + EOL).size < buf.size )
58
+ body.print buf[0 ... (buf.size - (EOL + boundary + EOL).size)]
59
+ buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
60
+ end
61
+
62
+ c = if bufsize < content_length
63
+ stdinput.read(bufsize)
64
+ else
65
+ stdinput.read(content_length)
66
+ end
67
+ if c.nil? || c.empty?
68
+ raise EOFError, "bad content body"
46
69
  end
47
- next
70
+ buf.concat(c)
71
+ content_length -= c.size
48
72
  end
49
-
50
- if head and ( (EOL + boundary + EOL).size < buf.size )
51
- body.print buf[0 ... (buf.size - (EOL + boundary + EOL).size)]
52
- buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
73
+
74
+ buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do
75
+ body.print $1
76
+ if "--" == $2
77
+ content_length = -1
78
+ end
79
+ boundary_end = $2.dup
80
+ ""
53
81
  end
54
-
55
- c = if bufsize < content_length
56
- stdinput.read(bufsize)
57
- else
58
- stdinput.read(content_length)
59
- end
60
- if c.nil? || c.empty?
61
- raise EOFError, "bad content body"
82
+
83
+ body.rewind
84
+
85
+ /Content-Disposition:.* filename="?([^\";]*)"?/ni.match(head)
86
+ filename = ($1 or "")
87
+ if /Mac/ni.match(env_table['HTTP_USER_AGENT']) and
88
+ /Mozilla/ni.match(env_table['HTTP_USER_AGENT']) and
89
+ (not /MSIE/ni.match(env_table['HTTP_USER_AGENT']))
90
+ filename = CGI::unescape(filename)
91
+ end
92
+
93
+ /Content-Type: (.*)/ni.match(head)
94
+ content_type = ($1 or "")
95
+
96
+ (class << body; self; end).class_eval do
97
+ alias local_path path
98
+ define_method(:original_filename) {filename.dup.taint}
99
+ define_method(:content_type) {content_type.dup.taint}
62
100
  end
63
- buf.concat(c)
64
- content_length -= c.size
65
- end
66
-
67
- buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do
68
- body.print $1
69
- if "--" == $2
70
- content_length = -1
101
+
102
+ /Content-Disposition:.* name="?([^\";]*)"?/ni.match(head)
103
+ name = $1.dup
104
+
105
+ if params.has_key?(name)
106
+ params[name].push(body)
107
+ else
108
+ params[name] = [body]
71
109
  end
72
- boundary_end = $2.dup
73
- ""
74
- end
75
-
76
- body.rewind
77
-
78
- /Content-Disposition:.* filename="?([^\";]*)"?/ni.match(head)
79
- filename = ($1 or "")
80
- if /Mac/ni.match(env_table['HTTP_USER_AGENT']) and
81
- /Mozilla/ni.match(env_table['HTTP_USER_AGENT']) and
82
- (not /MSIE/ni.match(env_table['HTTP_USER_AGENT']))
83
- filename = CGI::unescape(filename)
84
- end
85
-
86
- /Content-Type: (.*)/ni.match(head)
87
- content_type = ($1 or "")
88
-
89
- (class << body; self; end).class_eval do
90
- alias local_path path
91
- define_method(:original_filename) {filename.dup.taint}
92
- define_method(:content_type) {content_type.dup.taint}
93
- end
94
-
95
- /Content-Disposition:.* name="?([^\";]*)"?/ni.match(head)
96
- name = $1.dup
97
-
98
- if params.has_key?(name)
99
- params[name].push(body)
100
- else
101
- params[name] = [body]
110
+ break if buf.size == 0
111
+ break if content_length === -1
102
112
  end
103
- break if buf.size == 0
104
- break if content_length === -1
105
- end
106
- raise EOFError, "bad boundary end of body part" unless boundary_end=~/--/
107
-
108
- params
109
- end # read_multipart
110
- private :read_multipart
113
+ raise EOFError, "bad boundary end of body part" unless boundary_end=~/--/
114
+
115
+ params
116
+ end # read_multipart
117
+ private :read_multipart
118
+ end
111
119
  end
120
+
121
+ else
122
+ $stderr.puts "** Ruby version is up-to-date; cgi_multipart_eof_fix was not loaded"
112
123
  end
@@ -0,0 +1,25 @@
1
+
2
+ # http://www.bigbold.com/snippets/posts/show/2032
3
+ module Rake
4
+ module TaskManager
5
+ def redefine_task(task_class, args, &block)
6
+ task_name, deps = resolve_args(args)
7
+ task_name = task_class.scope_name(@scope, task_name)
8
+ deps = [deps] unless deps.respond_to?(:to_ary)
9
+ deps = deps.collect {|d| d.to_s }
10
+ task = @tasks[task_name.to_s] = task_class.new(task_name, self)
11
+ task.application = self
12
+ task.add_comment(@last_comment)
13
+ @last_comment = nil
14
+ task.enhance(deps, &block)
15
+ task
16
+ end
17
+ end
18
+ class Task
19
+ class << self
20
+ def redefine_task(args, &block)
21
+ Rake.application.redefine_task(self, args, &block)
22
+ end
23
+ end
24
+ end
25
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0.9
2
+ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: cgi_multipart_eof_fix
5
5
  version: !ruby/object:Gem::Version
6
- version: "2.1"
7
- date: 2007-02-05 00:00:00 -05:00
6
+ version: "2.2"
7
+ date: 2007-08-07 00:00:00 -04:00
8
8
  summary: Fix an exploitable bug in CGI multipart parsing which affects Ruby <= 1.8.5 when multipart boundary attribute contains a non-halting regular expression string.
9
9
  require_paths:
10
10
  - lib
11
- email: evan at cloudbur dot st
12
- homepage: http://blog.evanweaver.com
11
+ email: ""
12
+ homepage: http://blog.evanweaver.com/pages/code#cgi_multipart_eof_fix
13
13
  rubyforge_project: fauna
14
14
  description: Fix an exploitable bug in CGI multipart parsing which affects Ruby <= 1.8.5 when multipart boundary attribute contains a non-halting regular expression string.
15
15
  autorequire:
@@ -29,13 +29,17 @@ post_install_message:
29
29
  authors:
30
30
  - Evan Weaver
31
31
  files:
32
- - README.txt
33
- - LICENSE.txt
34
- - Rakefile
32
+ - test/cgi_multipart_eof_fix_test.rb
33
+ - lib/rake_task_redefine_task.rb
35
34
  - lib/cgi_multipart_eof_fix.rb
36
- - cgi_multipart_eof_fix_test.rb
37
- test_files:
38
- - cgi_multipart_eof_fix_test.rb
35
+ - Rakefile
36
+ - RUBY-LICENSE
37
+ - README
38
+ - Manifest
39
+ - CHANGELOG
40
+ - AFL3-LICENSE
41
+ test_files: []
42
+
39
43
  rdoc_options: []
40
44
 
41
45
  extra_rdoc_files: []
data/README.txt DELETED
@@ -1,45 +0,0 @@
1
-
2
- DESCRIPTION
3
-
4
- Fix an exploitable bug in CGI multipart parsing which affects Ruby <= 1.8.5
5
- when multipart boundary attribute contains a non-halting regular expression
6
- string. The boundary searcher in the CGI module does not properly escape
7
- the user-supplied parameter and will execute arbitrary regular expressions.
8
- The fix adds escaping for the user data.
9
-
10
- This is fix is cumulative with previous CGI multipart vulnerability fixes; see
11
- version 1.0.0 of the gem by Zed Shaw.
12
-
13
- SCOPE
14
-
15
- Affected: standalone CGI, Mongrel, WEBrick
16
- Unaffected: FastCGI
17
- Unknown: mod_ruby
18
-
19
- USAGE
20
-
21
- Install the hotfix gem and run the included test to verify the flaw is
22
- corrected. You must require the gem in every affected application, as follows:
23
-
24
- require 'rubygems'
25
- require 'cgi_multipart_eof_fix'
26
-
27
- If you only use mongrel_rails for application hosting, you may install mongrel
28
- like so:
29
-
30
- sudo gem install mongrel --source=http://mongrel.rubyforge.org/releases
31
-
32
- Then mongrel will require the fix for you, provided you have installed version 2.0.0
33
- of this gem. This is a hack, and mongrel may change in the future.
34
-
35
- RESOURCES
36
-
37
- http://www.ruby-lang.org/en/news/2006/12/04/another-dos-vulnerability-in-cgi-library/
38
- http://blog.evanweaver.com/articles/2006/12/05/cgi-rb-vulnerability-hotfix
39
- http://blog.evanweaver.com/articles/2006/12/05/new-cgi-rb-vulnerability
40
-
41
- LICENSE
42
-
43
- Copyright 2006, 2007 Cloudburst, LLC. Portions copyright 2006 Zed A. Shaw,
44
- Yukihiro Matsumoto and used with permission. Licensed under the AFL 3.0.
45
- See the included LICENSE.txt file.