From 8ee3267d26b4f87a9797573caa3dafb28e6945ee Mon Sep 17 00:00:00 2001 From: gotoyuzo Date: Sun, 18 May 2008 13:33:24 +0000 Subject: * 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/trunk@16453 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/webrick/test_cgi.rb | 9 +---- test/webrick/test_filehandler.rb | 82 ++++++++++++++++++++++++++++++++++++++-- test/webrick/utils.rb | 12 ++++++ 3 files changed, 92 insertions(+), 11 deletions(-) (limited to 'test/webrick') diff --git a/test/webrick/test_cgi.rb b/test/webrick/test_cgi.rb index 7d883af3b5..c5dbc0bf96 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"], :RequestHandler => Proc.new{|req, res| diff --git a/test/webrick/test_filehandler.rb b/test/webrick/test_filehandler.rb index 4c4a615f4a..371527e413 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) if defined? res.body.read res.body.read @@ -119,10 +123,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 dace41a8f3..39cadcff54 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) -- cgit v1.2.3