Skip to content

Commit

Permalink
Restrict broken mime parsing
Browse files Browse the repository at this point in the history
This commit restricts broken mime parsing to deal with a ReDOS
vulnerability.

[CVE-2022-30122]
  • Loading branch information
tenderlove committed May 27, 2022
1 parent 2f01891 commit d286516
Show file tree
Hide file tree
Showing 3 changed files with 5 additions and 18 deletions.
6 changes: 3 additions & 3 deletions lib/rack/multipart/parser.rb
Expand Up @@ -21,8 +21,7 @@ class Error < StandardError; end
TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/
CONDISP = /Content-Disposition:\s*#{TOKEN}\s*/i
VALUE = /"(?:\\"|[^"])*"|#{TOKEN}/
BROKEN_QUOTED = /^#{CONDISP}.*;\s*filename="(.*?)"(?:\s*$|\s*;\s*#{TOKEN}=)/i
BROKEN_UNQUOTED = /^#{CONDISP}.*;\s*filename=(#{TOKEN})/i
BROKEN = /^#{CONDISP}.*;\s*filename=(#{VALUE})/i
MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{EOL}/ni
MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:.*;\s*name=(#{VALUE})/ni
MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni
Expand Down Expand Up @@ -341,8 +340,9 @@ def get_filename(head)
elsif filename = params['filename']
filename = $1 if filename =~ /^"(.*)"$/
end
when BROKEN_QUOTED, BROKEN_UNQUOTED
when BROKEN
filename = $1
filename = $1 if filename =~ /^"(.*)"$/
end

return unless filename
Expand Down
@@ -1,6 +1,6 @@
--AaB03x
content-type: image/jpeg
content-disposition: attachment; name="files"; filename=""human" genome.jpeg"; modification-date="Wed, 12 Feb 1997 16:29:51 -0500";
content-disposition: attachment; name="files"; filename="\"human\" genome.jpeg"; modification-date="Wed, 12 Feb 1997 16:29:51 -0500";
Content-Description: a complete map of the human genome

contents
Expand Down
15 changes: 1 addition & 14 deletions test/spec_multipart.rb
Expand Up @@ -461,19 +461,6 @@ def initialize(*)
params["files"][:tempfile].read.must_equal "contents"
end

it "parse filename with unescaped quotes" do
env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_unescaped_quotes))
params = Rack::Multipart.parse_multipart(env)
params["files"][:type].must_equal "application/octet-stream"
params["files"][:filename].must_equal "escape \"quotes"
params["files"][:head].must_equal "content-disposition: form-data; " +
"name=\"files\"; " +
"filename=\"escape \"quotes\"\r\n" +
"content-type: application/octet-stream\r\n"
params["files"][:name].must_equal "files"
params["files"][:tempfile].read.must_equal "contents"
end

it "parse filename with escaped quotes and modification param" do
env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_escaped_quotes_and_modification_param))
params = Rack::Multipart.parse_multipart(env)
Expand All @@ -482,7 +469,7 @@ def initialize(*)
params["files"][:head].must_equal "content-type: image/jpeg\r\n" +
"content-disposition: attachment; " +
"name=\"files\"; " +
"filename=\"\"human\" genome.jpeg\"; " +
"filename=\"\\\"human\\\" genome.jpeg\"; " +
"modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";\r\n" +
"Content-Description: a complete map of the human genome\r\n"
params["files"][:name].must_equal "files"
Expand Down

0 comments on commit d286516

Please sign in to comment.