* uri encoding is now part of Rex::Text

* add junk param start
* add junk URI end


git-svn-id: file:///home/svn/incoming/trunk@3546 4d416f70-5f16-0410-b530-b9f4589650da
unstable
bmc 2006-02-27 19:55:22 +00:00
parent 53dfa3c83d
commit 279abda264
2 changed files with 50 additions and 40 deletions

View File

@ -60,6 +60,7 @@ class Request < Packet
self.proto = proto || DefaultProtocol
self.chunk_min_size = 1
self.chunk_max_size = 10
self.uri_encode_mode = 'hex-normal'
update_uri_parts
end
@ -101,8 +102,8 @@ class Request < Packet
# normalize out multiple slashes, directory traversal, and self referrential directories
def normalize!(str)
i = nil
while (str.gsub!(/(\/\.\/|\/\w+\/\.\.\/|\/\/)/,'/')); if (i.nil?); i = 1; else; i += 1; end; end
i = 0
while (str.gsub!(/(\/\.\/|\/\w+\/\.\.\/|\/\/)/,'/')); i += 1; end
i
end
@ -117,6 +118,12 @@ class Request < Packet
}
end
# /%3faaa=bbbbb
# which could possibly decode to "/?aaa=bbbbb", which if the IDS normalizes first, then splits the URI on ?, then it can be bypassed
if self.junk_param_start
str.sub!(/\//, '/%3f' + Rex::Text.rand_text_alpha(rand(5) + 1) + '=' + Rex::Text.rand_text_alpha(rand(10) + 1) + '/../')
end
# /RAND/../RAND../
if self.junk_directories
str.gsub!(/\//) {
@ -130,30 +137,22 @@ class Request < Packet
# ////
#
# NOTE: this must be done after all other odd directory junk, since they would cancel this out
# NOTE: this must be done after all other odd directory junk, since they would cancel this out, except junk_end_of_uri, since that a specific slash in a specific place
if self.junk_slashes
str.gsub!(/\//) {
'/' * (rand(3) + 2)
}
str.sub!(/^[\/]+/, '/') # only one beginning slash!
end
# / can't be encoded on most web servers...
if self.uri_encode_mode
case self.uri_encode_mode
when 'hex-all'
str = escape(str, 1).gsub!(/%2f/i, '/')
when 'hex-normal'
str = escape(str).gsub!(/%2f/i, '/')
when 'u-normal'
str = escape(str).gsub!(/%2f/i, '/').gsub!(/%/,'%u00')
when 'u-all'
str = escape(str, 1).gsub!(/%2f/i, '/').gsub!(/%/,'%u00')
when 'none'
# we do nothing here...
end
# /%20HTTP/1.0%0d%0a/../../
# which decodes to "/ HTTP/1.0\r\n"
if self.junk_end_of_uri
str.sub!(/^\//, '/%20HTTP/1.0%0d%0a/../../')
end
Rex::Text.uri_encode(str, self.uri_encode_mode)
if !PostRequests.include?(self.method)
if param_string.size > 0
str += '?' + param_string
@ -173,13 +172,13 @@ class Request < Packet
end
if value.kind_of?(Array)
value.each { |subvalue|
params.push(self.escape(param) + '=' + self.escape(subvalue))
params.push(Rex::Text.uri_encode(param, self.uri_encode_mode) + '=' + Rex::Text.uri_encode(subvalue, self.uri_encode_mode))
}
else
if !value.nil?
params.push(self.escape(param) + '=' + self.escape(value))
params.push(Rex::Text.uri_encode(param, self.uri_encode_mode) + '=' + Rex::Text.uri_encode(value, self.uri_encode_mode))
else
params.push(self.escape(param))
params.push(Rex::Text.uri_encode(param, self.uri_encode_mode))
end
end
}
@ -199,15 +198,6 @@ class Request < Packet
update_uri_parts
end
# Returns a URI escaped version of the provided string, by providing an additional argument, all characters are escaped
def escape(str, all = nil)
if all
return str.gsub(/./) { |s| Rex::Text.to_hex(s, '%') }
else
return str.gsub(/[^a-zA-Z1-9]/) { |s| Rex::Text.to_hex(s, '%') }
end
end
# Returns a request packet
def to_s
str = ''
@ -303,7 +293,7 @@ class Request < Packet
# add junk slashes
attr_accessor :junk_slashes
# add junk self referring directories (aka /././././
# add junk self referring directories (aka /././././)
attr_accessor :junk_self_referring_directories
# add junk params
@ -312,8 +302,15 @@ class Request < Packet
# add junk pipeline requests
attr_accessor :junk_pipeline
# add junk start of params
attr_accessor :junk_param_start
# add junk end of URI
attr_accessor :junk_end_of_uri
# encoding uri
attr_accessor :uri_encode_mode
protected

View File

@ -76,8 +76,15 @@ class Rex::Proto::Http::Request::UnitTest < Test::Unit::TestCase
h = junk_request
h.junk_self_referring_directories = 1
assert_equal('/././foo/././bar.html', h.uri, 'junk referring directories')
end
h = junk_request
h.junk_param_start = 1
assert_equal('/%3fgf=XjLyc/../foo/bar.html', h.uri, 'junk start of params')
h = junk_request
h.junk_end_of_uri = 1
assert_equal('/%20HTTP/1.0%0d%0a/../../foo/bar.html', h.uri, 'junk end of URI')
end
def test_params
srand(0)
@ -156,14 +163,16 @@ class Rex::Proto::Http::Request::UnitTest < Test::Unit::TestCase
h.junk_slashes = 1
h.junk_directories = 1
h.junk_self_referring_directories = 1
h.junk_end_of_uri = 1
h.junk_param_start = 1
seen = {}
expect = [
{"//"=>121, "/./"=>25, "/w/../"=>3},
{"//"=>107, "/./"=>25, "/w/../"=>3},
{"//"=>120, "/./"=>30, "/w/../"=>4},
{"//"=>113, "/./"=>25, "/w/../"=>3},
{"//"=>120, "/./"=>25, "/w/../"=>3},
{"//"=>145, "/./"=>35, "param"=>1, "http"=>1, "/w/../"=>3},
{"//"=>149, "/./"=>35, "param"=>1, "http"=>1, "/w/../"=>3},
{"//"=>130, "/./"=>30, "param"=>1, "http"=>1, "/w/../"=>2},
{"//"=>165, "/./"=>40, "param"=>1, "http"=>1, "/w/../"=>4},
{"//"=>145, "/./"=>35, "param"=>1, "http"=>1, "/w/../"=>3},
]
i = 0
5.times {
@ -172,11 +181,15 @@ class Rex::Proto::Http::Request::UnitTest < Test::Unit::TestCase
assert_nil(seen[str], 'all the junk, not a dup rand')
seen[str] = 1
seen = { '/./' => 0, '//' => 0, '/w/../' => 0 }
seen = { '/./' => 0, '//' => 0, '/w/../' => 0, 'http' => 0, 'param' => 0}
matched = 1
while matched == 1
# p str
if str.sub!(/\/\w+\/\.\.\//, '/')
if str.sub!(/\/%20HTTP\/1.0%0d%0a\/\.\.\/\.\.\//, '/')
seen['http'] += 1;
elsif str.sub!(/\/%3f\w+=\w+\/\.\.\//i, '/')
seen['param'] += 1;
elsif str.sub!(/\/\w+\/\.\.\//, '/')
seen['/./'] += 1;
elsif str.sub!(/\/\//, '/')
seen['//'] += 1;
@ -187,7 +200,7 @@ class Rex::Proto::Http::Request::UnitTest < Test::Unit::TestCase
end
end
assert_equal('/foo/bar.html', str, 'normalized')
assert_equal('/foo/bar.html', str, 'normalized')
assert_equal(expect[i], seen, 'expected counts')
i += 1
}