mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-10-29 18:07:27 +01:00
Patches from <anon>
git-svn-id: file:///home/svn/incoming/trunk@3310 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
parent
d0c8775f56
commit
8049b32cbc
@ -69,6 +69,8 @@ module Common
|
||||
end
|
||||
|
||||
def self.platform_icons(platform)
|
||||
# nil?
|
||||
return "" if (platform.nil?)
|
||||
# If this module has no platforms, then we don't show any icons...
|
||||
return "" if (platform.empty?)
|
||||
|
||||
|
@ -157,12 +157,16 @@ protected
|
||||
register_options(
|
||||
[
|
||||
OptString.new('URIPATH', [ false, "The URI to use for this exploit (default is random)"]),
|
||||
], Exploit::Remote::HttpServer)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('DisableGzip', [ false, "Disable the use of GZIP on HTTP responses", false ]),
|
||||
], Exploit::Remote::HttpServer)
|
||||
], Exploit::Remote::HttpServer
|
||||
)
|
||||
|
||||
register_evasion_options(
|
||||
[
|
||||
OptBool.new('HTTP::gzip', [false, 'Enable compression of HTTP responses via "Content-Encoding: gzip"', 'false']),
|
||||
OptBool.new('HTTP::chunked', [false, 'Enable chunking of HTTP responses via "Transfer-Encoding: chunked"', 'false']),
|
||||
], Exploit::Remote::HttpServer
|
||||
)
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
@ -171,8 +175,8 @@ protected
|
||||
# set.
|
||||
#
|
||||
def use_gzip
|
||||
if (!Rex::Text.gzip_present? and datastore['DisableGzip'] != true)
|
||||
raise RuntimeError, "GZIP support was not detected, set the DisableGzip advanced option to use non-compressed HTTP responses"
|
||||
if (!Rex::Text.gzip_present? and datastore['HTTP::gzip'] == true)
|
||||
raise RuntimeError, "GZIP support was not detected, yet the HTTP::gzip option was set. WTF?"
|
||||
end
|
||||
end
|
||||
|
||||
@ -204,6 +208,8 @@ protected
|
||||
self.service = Rex::ServiceManager.start(Rex::Proto::Http::Server,
|
||||
opts['ServerPort'].to_i, opts['ServerHost'])
|
||||
|
||||
self.service.server_name = 'Apache'
|
||||
|
||||
# Default the procedure of the URI to on_request_uri if one isn't
|
||||
# provided.
|
||||
uopts = {
|
||||
@ -259,35 +265,32 @@ protected
|
||||
return Rex::Proto::Http::Response.new(code, message, proto);
|
||||
end
|
||||
|
||||
#
|
||||
# Transmits an HTML response to the supplied client.
|
||||
#
|
||||
def send_html_response(cli, body, headers = {})
|
||||
response = create_response
|
||||
|
||||
#
|
||||
# Transmits a response to the supplied client, default content-type is text/html
|
||||
#
|
||||
# Payload evasions are implemented here!
|
||||
#
|
||||
def send_response(cli, body, headers = {})
|
||||
response = create_response
|
||||
response['Content-Type'] = 'text/html'
|
||||
response.body = body
|
||||
|
||||
response.body = body
|
||||
|
||||
if (datastore['HTTP::gzip'] == true)
|
||||
self.use_gzip # make sure...
|
||||
response.body = Rex::Text.gzip(response.body)
|
||||
response['Content-Encoding'] = 'gzip'
|
||||
end
|
||||
|
||||
if (datastore['HTTP::chunked'] == true)
|
||||
response.auto_cl = false
|
||||
response.transfer_chunked = true
|
||||
end
|
||||
|
||||
headers.each_pair { |k,v| response[k] = v }
|
||||
|
||||
cli.send_response(response)
|
||||
end
|
||||
|
||||
#
|
||||
# Transmits an gzip-encoded HTML response to the supplied client.
|
||||
#
|
||||
def send_html_gzip_response(cli, body, headers = {})
|
||||
# Just call the normal response method if gzip is disabled.
|
||||
return send_html_response(cli, body, headers) if (datastore['DisableGzip'])
|
||||
|
||||
response = create_response
|
||||
response['Content-Type'] = 'text/html'
|
||||
response['Content-Encoding'] = 'gzip'
|
||||
response.body = Rex::Text.gzip(body)
|
||||
|
||||
headers.each_pair { |k,v| response[k] = v }
|
||||
|
||||
cli.send_response(response)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Sends a 302 redirect to the client
|
||||
|
@ -122,17 +122,47 @@ class Packet
|
||||
return comp
|
||||
end
|
||||
|
||||
#
|
||||
# Build a 'Transfer-Encoding: chunked' payload with random chunk sizes
|
||||
#
|
||||
def chunk(str, min_size = 1, max_size = 1000)
|
||||
chunked = ''
|
||||
|
||||
# min chunk size is 1 byte
|
||||
if (min_size < 1); min_size = 1; end
|
||||
|
||||
# don't be dumb
|
||||
if (max_size < min_size); max_size = min_size; end
|
||||
|
||||
while (str.size > 0)
|
||||
chunk = str.slice!(0, rand(max_size - min_size) + min_size)
|
||||
chunked += sprintf("%x", chunk.size) + "\r\n" + chunk + "\r\n"
|
||||
end
|
||||
chunked += "0\r\n\r\n"
|
||||
end
|
||||
|
||||
#
|
||||
# Converts the packet to a string.
|
||||
#
|
||||
def to_s
|
||||
content = self.body.dup
|
||||
# Update the content length field in the header with the body length.
|
||||
if (self.body and self.auto_cl)
|
||||
self.headers['Content-Length'] = self.body.length
|
||||
if (content)
|
||||
if (self.auto_cl == true && self.transfer_chunked == true)
|
||||
raise RuntimeError, "'Content-Length' and 'Transfer-Encoding: chunked' are incompatable"
|
||||
elsif self.auto_cl == true
|
||||
self.headers['Content-Length'] = content.length
|
||||
elsif self.transfer_chunked == true
|
||||
if self.proto != '1.1'
|
||||
raise RuntimeError, 'Chunked encoding is only available via 1.1'
|
||||
end
|
||||
self.headers['Transfer-Encoding'] = 'chunked'
|
||||
content = self.chunk(content, self.chunk_min_size, self.chunk_max_size)
|
||||
end
|
||||
end
|
||||
|
||||
str = self.headers.to_s(cmd_string)
|
||||
str += self.body || ''
|
||||
str += content || ''
|
||||
end
|
||||
|
||||
#
|
||||
@ -164,7 +194,11 @@ class Packet
|
||||
attr_accessor :body
|
||||
attr_accessor :auto_cl
|
||||
attr_accessor :max_data
|
||||
attr_accessor :transfer_chunked
|
||||
attr_reader :incomplete
|
||||
|
||||
attr_accessor :chunk_min_size
|
||||
attr_accessor :chunk_max_size
|
||||
|
||||
protected
|
||||
|
||||
@ -172,7 +206,6 @@ protected
|
||||
attr_writer :error
|
||||
attr_writer :incomplete
|
||||
attr_accessor :body_bytes_left
|
||||
attr_accessor :transfer_chunked
|
||||
attr_accessor :inside_chunk
|
||||
|
||||
##
|
||||
|
@ -33,13 +33,21 @@ class Rex::Proto::Http::Request::UnitTest < Test::Unit::TestCase
|
||||
"Eat: Babies\r\n" +
|
||||
"\r\n")
|
||||
|
||||
assert_equal('POST', h.method)
|
||||
assert_equal('/foo', h.uri)
|
||||
assert_equal('1.0', h.proto)
|
||||
assert_equal("POST /foo HTTP/1.0\r\n", h.cmd_string)
|
||||
assert_equal('POST', h.method, 'method')
|
||||
assert_equal('/foo', h.uri, 'uri')
|
||||
assert_equal('1.0', h.proto, 'proto')
|
||||
assert_equal('Babies', h['Eat'], 'header')
|
||||
|
||||
assert_equal("POST /foo HTTP/1.0\r\n", h.cmd_string, 'cmd_string')
|
||||
|
||||
h.method = 'GET'
|
||||
assert_equal("GET /foo HTTP/1.0\r\n", h.cmd_string)
|
||||
assert_equal('Babies', h['Eat'])
|
||||
assert_equal("GET /foo HTTP/1.0\r\n", h.cmd_string, 'set method')
|
||||
|
||||
h.uri = '/bar'
|
||||
assert_equal("GET /bar HTTP/1.0\r\n", h.cmd_string, 'set uri')
|
||||
|
||||
h.proto = '1.2'
|
||||
assert_equal("GET /bar HTTP/1.2\r\n", h.cmd_string, 'set proto')
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -48,6 +48,10 @@ class Response < Packet
|
||||
|
||||
# Default responses to auto content length on
|
||||
self.auto_cl = true
|
||||
|
||||
# default chunk sizes (if chunked is used)
|
||||
self.chunk_min_size = 1
|
||||
self.chunk_max_size = 10
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -20,9 +20,75 @@ class Rex::Proto::Http::Response::UnitTest < Test::Unit::TestCase
|
||||
"HTTP/1.1 200 OK\r\n" +
|
||||
"Foo: Fishing\r\n" +
|
||||
"Content-Length: 0\r\n" +
|
||||
"Chicken: 47\r\n\r\n", h.to_s)
|
||||
"Chicken: 47\r\n\r\n", h.to_s, 'to_s w/o body')
|
||||
|
||||
h.body = 'hi mom'
|
||||
assert_equal(
|
||||
"HTTP/1.1 200 OK\r\n" +
|
||||
"Foo: Fishing\r\n" +
|
||||
"Content-Length: 6\r\n" +
|
||||
"Chicken: 47\r\n\r\nhi mom", h.to_s, 'to_s w/ body')
|
||||
end
|
||||
|
||||
|
||||
def test_chunked
|
||||
h = Klass.new
|
||||
|
||||
h.headers['Foo'] = 'Fishing'
|
||||
h.headers['Chicken'] = 47
|
||||
h.auto_cl = false
|
||||
h.transfer_chunked = true
|
||||
|
||||
|
||||
assert_equal(
|
||||
"HTTP/1.1 200 OK\r\n" +
|
||||
"Transfer-Encoding: chunked\r\n" +
|
||||
"Foo: Fishing\r\n" +
|
||||
"Chicken: 47\r\n\r\n0\r\n\r\n", h.to_s, 'chunked w/o body'
|
||||
)
|
||||
|
||||
srand(0)
|
||||
h.body = Rex::Text.rand_text_alphanumeric(100)
|
||||
assert_equal(
|
||||
"HTTP/1.1 200 OK\r\n" +
|
||||
"Transfer-Encoding: chunked\r\n" +
|
||||
"Foo: Fishing\r\n" +
|
||||
"Chicken: 47\r\n\r\n" +
|
||||
"5\r\nsv1AD\r\n7\r\n7DnJTVy\r\n5\r\nkXGYY\r\n5\r\nM6Bmn\r\n4\r\nXuYR\r\n5\r\nlZNIJ\r\n5\r\nUzQzF\r\n9\r\nPvASjYxzd\r\n5\r\nTTOng\r\n4\r\nBJ5g\r\n8\r\nfK0XjLy3\r\n6\r\nciAAk1\r\n6\r\nFmo0RP\r\n1\r\nE\r\n2\r\npq\r\n6\r\n6f4BBn\r\n4\r\np5jm\r\n1\r\n3\r\n6\r\nLuSbAO\r\n1\r\nj\r\n2\r\n1M\r\n3\r\n5qU\r\n0\r\n\r\n",
|
||||
h.to_s, 'random chunk sizes'
|
||||
)
|
||||
|
||||
h.chunk_max_size = 1
|
||||
h.body = 'hi mom'
|
||||
assert_equal(
|
||||
"HTTP/1.1 200 OK\r\n" +
|
||||
"Transfer-Encoding: chunked\r\n" +
|
||||
"Foo: Fishing\r\n" +
|
||||
"Chicken: 47\r\n\r\n" +
|
||||
"1\r\nh\r\n1\r\ni\r\n1\r\n \r\n1\r\nm\r\n1\r\no\r\n1\r\nm\r\n0\r\n\r\n",
|
||||
h.to_s, '1 byte chunks'
|
||||
)
|
||||
|
||||
h.chunk_min_size = 2
|
||||
assert_equal(
|
||||
"HTTP/1.1 200 OK\r\n" +
|
||||
"Transfer-Encoding: chunked\r\n" +
|
||||
"Foo: Fishing\r\n" +
|
||||
"Chicken: 47\r\n\r\n" +
|
||||
"2\r\nhi\r\n2\r\n m\r\n2\r\nom\r\n0\r\n\r\n",
|
||||
h.to_s, '2 byte chunks'
|
||||
)
|
||||
|
||||
h = Klass.new(200, 'OK', '1.0')
|
||||
h.body = 'hi mom'
|
||||
h.auto_cl = false
|
||||
h.transfer_chunked = true
|
||||
assert_raise(Rex::RuntimeError, 'chunked encoding via 1.0') {
|
||||
h.to_s
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
def test_from_s
|
||||
h = Klass.new
|
||||
|
||||
|
@ -103,6 +103,7 @@ class Server
|
||||
self.listen_host = listen_host
|
||||
self.listen_port = port
|
||||
self.listener = nil
|
||||
self.server_name = DefaultServer
|
||||
self.resources = {}
|
||||
end
|
||||
|
||||
@ -195,7 +196,7 @@ class Server
|
||||
# Adds Server headers and stuff.
|
||||
#
|
||||
def add_response_headers(resp)
|
||||
resp['Server'] = DefaultServer
|
||||
resp['Server'] = self.server_name
|
||||
end
|
||||
|
||||
#
|
||||
@ -233,6 +234,11 @@ class Server
|
||||
end
|
||||
|
||||
attr_accessor :listen_port, :listen_host
|
||||
|
||||
#
|
||||
# Server name used by this servier instance
|
||||
#
|
||||
attr_accessor :server_name
|
||||
|
||||
protected
|
||||
|
||||
@ -329,6 +335,7 @@ protected
|
||||
close_client(cli)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
@ -348,13 +348,27 @@ module Text
|
||||
#
|
||||
# Compresses a string using gzip
|
||||
#
|
||||
def self.gzip(str)
|
||||
def self.gzip(str, level = 9)
|
||||
raise RuntimeError, "Gzip support is not present." if (!gzip_present?)
|
||||
raise RuntimeError, "Invalid gzip compression level" if (level < 1 or level > 9)
|
||||
|
||||
s = ""
|
||||
gz = Zlib::GzipWriter.new(StringIO.new(s), level)
|
||||
gz << str
|
||||
gz.close
|
||||
return s
|
||||
end
|
||||
|
||||
#
|
||||
# Uncompresses a string using gzip
|
||||
#
|
||||
def self.ungzip(str)
|
||||
raise RuntimeError, "Gzip support is not present." if (!gzip_present?)
|
||||
|
||||
s = ""
|
||||
w = Zlib::GzipWriter.new(StringIO.new(s))
|
||||
w << str
|
||||
w.close
|
||||
gz = Zlib::GzipReader.new(StringIO.new(str))
|
||||
s << gz.read
|
||||
gz.close
|
||||
return s
|
||||
end
|
||||
|
||||
@ -409,7 +423,5 @@ protected
|
||||
buf
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
@ -75,7 +75,7 @@ class Exploits::Windows::Browser::AimGoaway < Msf::Exploit::Remote
|
||||
print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...")
|
||||
|
||||
# Transmit the response to the client
|
||||
send_html_response(cli, content)
|
||||
send_response(cli, content)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -72,7 +72,7 @@ class Exploits::Windows::Browser::MetafileAbortProc < Msf::Exploit::Remote
|
||||
get_resource + '/' +
|
||||
Rex::Text.rand_text_alphanumeric(rand(256)+16) +
|
||||
".#{ext}'><body>One second please...</body></html>"
|
||||
send_html_gzip_response(cli, html)
|
||||
send_response(cli, html)
|
||||
return
|
||||
end
|
||||
|
||||
@ -80,7 +80,7 @@ class Exploits::Windows::Browser::MetafileAbortProc < Msf::Exploit::Remote
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
# Transmit the compressed response to the client
|
||||
send_html_gzip_response(cli, generate_metafile(p), { 'Content-Type' => 'text/plain' })
|
||||
send_response(cli, generate_metafile(p), { 'Content-Type' => 'text/plain' })
|
||||
|
||||
handler(cli)
|
||||
end
|
||||
|
@ -63,8 +63,7 @@ class Exploits::Windows::Browser::MS03_020_Ie_ObjectType < Msf::Exploit::Remote
|
||||
else
|
||||
print_status("Sending 404 to user agent: #{request['User-Agent']}")
|
||||
|
||||
cli.send_response(
|
||||
create_response(404, 'File not found'))
|
||||
cli.send_response(create_response(404, 'File not found'))
|
||||
|
||||
return
|
||||
end
|
||||
@ -90,7 +89,7 @@ class Exploits::Windows::Browser::MS03_020_Ie_ObjectType < Msf::Exploit::Remote
|
||||
print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...")
|
||||
|
||||
# Transmit the response to the client
|
||||
send_html_response(cli, content)
|
||||
send_response(cli, content)
|
||||
end
|
||||
|
||||
end
|
||||
|
25
msfcli
25
msfcli
@ -16,7 +16,7 @@ Indent = ' '
|
||||
# Initialize the simplified framework instance.
|
||||
$framework = Msf::Simple::Framework.create
|
||||
|
||||
if (ARGV.length <= 1)
|
||||
if (ARGV.length < 1)
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Header' => 'Exploits',
|
||||
'Indent' => 4,
|
||||
@ -42,13 +42,31 @@ end
|
||||
# Initialize the user interface
|
||||
exploit.init_ui($stdout, $stdin)
|
||||
|
||||
# Evalulate the command
|
||||
mode = ARGV.pop.downcase
|
||||
# Evalulate the command (default to "help")
|
||||
mode = ARGV.pop || 'h'
|
||||
|
||||
# Import options
|
||||
exploit.datastore.import_options_from_s(ARGV.join(' '))
|
||||
|
||||
case mode.downcase
|
||||
when 'h'
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Header' => "Usage: #{$0} #{exploit_name} <option=value> [mode]",
|
||||
'Indent' => 4,
|
||||
'Columns' => ['Mode', 'Description']
|
||||
)
|
||||
|
||||
tbl << ['(H)elp', "you're looking at it baby!"]
|
||||
tbl << ['(S)ummary', 'show information about this module']
|
||||
tbl << ['(O)ptions', 'show available options for this module']
|
||||
tbl << ['(A)dvanced', 'show available advanced options for this module']
|
||||
tbl << ['(I)ds Evasion', 'show available ids evasion options for this module']
|
||||
tbl << ['(P)ayloads', 'show available payloads for this module']
|
||||
tbl << ['(T)argets', 'show available targets for this module']
|
||||
tbl << ['(C)heck', 'Attempt to check if the target is vulnerable']
|
||||
tbl << ['(E)xploit', 'Attempt to exploit the target']
|
||||
|
||||
$stdout.puts tbl.to_s
|
||||
when "s"
|
||||
$stdout.puts("\n" + Msf::Serializer::ReadableText.dump_module(exploit, Indent))
|
||||
when "o"
|
||||
@ -102,4 +120,5 @@ case mode.downcase
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
$stdout.puts
|
||||
|
Loading…
Reference in New Issue
Block a user