diff options
author | gotoyuzo <gotoyuzo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-05-20 16:35:25 +0000 |
---|---|---|
committer | gotoyuzo <gotoyuzo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-05-20 16:35:25 +0000 |
commit | 4fc6b25289fe83e4cede024d9fea83217bffdc7e (patch) | |
tree | 10010c121dc4363dff8e08de11d67099bdff6459 /test/webrick | |
parent | c54db30e883b27d856573639c5c4e62bddb4831e (diff) |
* lib/webrick/httpservlet/filehandler.rb: should normalize path
name in path_info to prevent script disclosure vulnerability on
DOSISH filesystems. (fix: CVE-2008-1891)
Note: NTFS/FAT filesystem should not be published by the platforms
other than Windows. Pathname interpretation (including short
filename) is less than perfect.
* lib/webrick/httpservlet/abstract.rb
(WEBrick::HTTPServlet::AbstracServlet#redirect_to_directory_uri):
should escape the value of Location: header.
* lib/webrick/httpservlet/cgi_runner.rb: accept interpreter
command line arguments.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_6@16495 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'test/webrick')
-rw-r--r-- | test/webrick/.htaccess | 1 | ||||
-rw-r--r-- | test/webrick/test_cgi.rb | 9 | ||||
-rw-r--r-- | test/webrick/test_filehandler.rb | 82 | ||||
-rw-r--r-- | test/webrick/utils.rb | 12 | ||||
-rwxr-xr-x | test/webrick/webrick_long_filename.cgi | 36 |
5 files changed, 129 insertions, 11 deletions
diff --git a/test/webrick/.htaccess b/test/webrick/.htaccess new file mode 100644 index 0000000000..69d4659b9f --- /dev/null +++ b/test/webrick/.htaccess @@ -0,0 +1 @@ +this file should not be published. diff --git a/test/webrick/test_cgi.rb b/test/webrick/test_cgi.rb index 7e3f4ee5f0..b39fe2661c 100644 --- a/test/webrick/test_cgi.rb +++ b/test/webrick/test_cgi.rb @@ -1,20 +1,13 @@ require "webrick" require File.join(File.dirname(__FILE__), "utils.rb") require "test/unit" -begin - loadpath = $:.dup - $:.replace($: | [File.expand_path("../ruby", File.dirname(__FILE__))]) - require 'envutil' -ensure - $:.replace(loadpath) -end class TestWEBrickCGI < Test::Unit::TestCase def test_cgi accepted = started = stopped = 0 requested0 = requested1 = 0 config = { - :CGIInterpreter => EnvUtil.rubybin, + :CGIInterpreter => TestWEBrick::RubyBin, :DocumentRoot => File.dirname(__FILE__), :DirectoryIndex => ["webrick.cgi"], } diff --git a/test/webrick/test_filehandler.rb b/test/webrick/test_filehandler.rb index e1299a4589..2c7d97fa70 100644 --- a/test/webrick/test_filehandler.rb +++ b/test/webrick/test_filehandler.rb @@ -9,6 +9,10 @@ class WEBrick::TestFileHandler < Test::Unit::TestCase klass.new(WEBrick::Config::HTTP, filename) end + def windows? + File.directory?("\\") + end + def get_res_body(res) return res.body.read rescue res.body end @@ -115,10 +119,82 @@ class WEBrick::TestFileHandler < Test::Unit::TestCase http = Net::HTTP.new(addr, port) req = Net::HTTP::Get.new("/../../") http.request(req){|res| assert_equal("400", res.code) } - req = Net::HTTP::Get.new( - "/..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5cboot.ini" - ) + req = Net::HTTP::Get.new("/..%5c../#{File.basename(__FILE__)}") + http.request(req){|res| assert_equal(windows? ? "200" : "404", res.code) } + req = Net::HTTP::Get.new("/..%5c..%5cruby.c") http.request(req){|res| assert_equal("404", res.code) } end end + + def test_unwise_in_path + if windows? + config = { :DocumentRoot => File.dirname(__FILE__), } + this_file = File.basename(__FILE__) + TestWEBrick.start_httpserver(config) do |server, addr, port| + http = Net::HTTP.new(addr, port) + req = Net::HTTP::Get.new("/..%5c..") + http.request(req){|res| assert_equal("301", res.code) } + end + end + end + + def test_short_filename + config = { + :CGIInterpreter => TestWEBrick::RubyBin, + :DocumentRoot => File.dirname(__FILE__), + :CGIPathEnv => ENV['PATH'], + } + TestWEBrick.start_httpserver(config) do |server, addr, port| + http = Net::HTTP.new(addr, port) + + req = Net::HTTP::Get.new("/webric~1.cgi/test") + http.request(req) do |res| + if windows? + assert_equal("200", res.code) + assert_equal("/test", res.body) + else + assert_equal("404", res.code) + end + end + + req = Net::HTTP::Get.new("/.htaccess") + http.request(req) {|res| assert_equal("404", res.code) } + req = Net::HTTP::Get.new("/htacce~1") + http.request(req) {|res| assert_equal("404", res.code) } + req = Net::HTTP::Get.new("/HTACCE~1") + http.request(req) {|res| assert_equal("404", res.code) } + end + end + + def test_script_disclosure + config = { + :CGIInterpreter => TestWEBrick::RubyBin, + :DocumentRoot => File.dirname(__FILE__), + :CGIPathEnv => ENV['PATH'], + } + TestWEBrick.start_httpserver(config) do |server, addr, port| + http = Net::HTTP.new(addr, port) + + req = Net::HTTP::Get.new("/webrick.cgi/test") + http.request(req) do |res| + assert_equal("200", res.code) + assert_equal("/test", res.body) + end + + response_assertion = Proc.new do |res| + if windows? + assert_equal("200", res.code) + assert_equal("/test", res.body) + else + assert_equal("404", res.code) + end + end + req = Net::HTTP::Get.new("/webrick.cgi%20/test") + http.request(req, &response_assertion) + req = Net::HTTP::Get.new("/webrick.cgi./test") + http.request(req, &response_assertion) + req = Net::HTTP::Get.new("/webrick.cgi::$DATA/test") + http.request(req, &response_assertion) + end + end end diff --git a/test/webrick/utils.rb b/test/webrick/utils.rb index f1e6e4b027..5db94e6cd5 100644 --- a/test/webrick/utils.rb +++ b/test/webrick/utils.rb @@ -1,3 +1,10 @@ +begin + loadpath = $:.dup + $:.replace($: | [File.expand_path("../ruby", File.dirname(__FILE__))]) + require 'envutil' +ensure + $:.replace(loadpath) +end require "webrick" begin require "webrick/https" @@ -12,6 +19,11 @@ module TestWEBrick return self end + RubyBin = "\"#{EnvUtil.rubybin}\"" + RubyBin << " \"-I#{File.expand_path("../..", File.dirname(__FILE__))}/lib\"" + RubyBin << " \"-I#{File.dirname(EnvUtil.rubybin)}/.ext/common\"" + RubyBin << " \"-I#{File.dirname(EnvUtil.rubybin)}/.ext/#{RUBY_PLATFORM}\"" + module_function def start_server(klass, config={}, &block) diff --git a/test/webrick/webrick_long_filename.cgi b/test/webrick/webrick_long_filename.cgi new file mode 100755 index 0000000000..73ba729407 --- /dev/null +++ b/test/webrick/webrick_long_filename.cgi @@ -0,0 +1,36 @@ +#!ruby -d +require "webrick/cgi" + +class TestApp < WEBrick::CGI + def do_GET(req, res) + res["content-type"] = "text/plain" + if (p = req.path_info) && p.length > 0 + res.body = p + elsif (q = req.query).size > 0 + res.body = q.keys.sort.collect{|key| + q[key].list.sort.collect{|v| + "#{key}=#{v}" + }.join(", ") + }.join(", ") + elsif %r{/$} =~ req.request_uri.to_s + res.body = "" + res.body << req.request_uri.to_s << "\n" + res.body << req.script_name + elsif !req.cookies.empty? + res.body = req.cookies.inject(""){|result, cookie| + result << "%s=%s\n" % [cookie.name, cookie.value] + } + res.cookies << WEBrick::Cookie.new("Customer", "WILE_E_COYOTE") + res.cookies << WEBrick::Cookie.new("Shipping", "FedEx") + else + res.body = req.script_name + end + end + + def do_POST(req, res) + do_GET(req, res) + end +end + +cgi = TestApp.new +cgi.start |