From 062529ce3b9d6f99abefeec19ccba7096d34fcdb Mon Sep 17 00:00:00 2001 From: James Lee Date: Fri, 30 Jan 2015 15:24:15 -0600 Subject: [PATCH] Move HttpServer::HTML into its own file --- lib/msf/core/exploit/http/server.rb | 252 +---------------- lib/msf/core/exploit/http/server/html.rb | 254 ++++++++++++++++++ .../exploit/http/{ => server}/php_include.rb | 0 3 files changed, 256 insertions(+), 250 deletions(-) create mode 100644 lib/msf/core/exploit/http/server/html.rb rename lib/msf/core/exploit/http/{ => server}/php_include.rb (100%) diff --git a/lib/msf/core/exploit/http/server.rb b/lib/msf/core/exploit/http/server.rb index e83649f121..0530f73b18 100644 --- a/lib/msf/core/exploit/http/server.rb +++ b/lib/msf/core/exploit/http/server.rb @@ -14,6 +14,8 @@ module Msf # ### module Exploit::Remote::HttpServer + require 'msf/core/exploit/http/server/html' + require 'msf/core/exploit/http/server/php_include' include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report @@ -699,255 +701,5 @@ module Exploit::Remote::HttpServer # allow this module to be patched at initialization-time Metasploit::Concern.run(self) end - -### -# -# This module provides methods for exploiting an HTTP client by acting -# as an HTTP server. -# -### -module Exploit::Remote::HttpServer::HTML - - include Msf::Exploit::Remote::HttpServer - - UTF_NONE = 'none' - UTF_7 = 'utf-7' - UTF_7_ALL = 'utf-7-all' - UTF_8 = 'utf-8' - UTF_16_LE = 'utf-16le' - UTF_16_BE = 'utf-16be' - UTF_16_BE_MARKER = 'utf-16be-marker' - UTF_32_LE = 'utf-32le' - UTF_32_BE = 'utf-32be' - -protected - - def initialize(info = {}) - super - - register_evasion_options( - [ - # utf-8, utf-7 and utf-7-all are currently not supported by - # most browsers. as such, they are not added by default. The - # mixin supports encoding using them, however they are not - # listed in the Option. - OptEnum.new('HTML::unicode', [false, 'Enable HTTP obfuscation via unicode', UTF_NONE, [UTF_NONE, UTF_16_LE, UTF_16_BE, UTF_16_BE_MARKER, UTF_32_LE, UTF_32_BE]]), - OptEnum.new('HTML::base64', [false, 'Enable HTML obfuscation via an embeded base64 html object (IE not supported)', 'none', ['none', 'plain', 'single_pad', 'double_pad', 'random_space_injection']]), - OptInt.new('HTML::javascript::escape', [false, 'Enable HTML obfuscation via HTML escaping (number of iterations)', 0]), - ], Exploit::Remote::HttpServer::HTML) - end - - # - # Obfuscates symbols found within a javascript string. - # - # Returns an ObfuscateJS object - # - def obfuscate_js(javascript, opts) - js = Rex::Exploitation::ObfuscateJS.new(javascript, opts) - js.obfuscate - return js - end - - # - # Encrypts a given javascript string using the provided key. - # - # Returns a string containing the encrypted string and a loader - # - def encrypt_js(javascript, key) - Rex::Exploitation::EncryptJS.encrypt(javascript, key) - end - - # - # Returns the heaplib javascript, including any custom javascript supplied - # by the caller. - # - def heaplib(custom_js = '', opts = {}) - Rex::Exploitation::HeapLib.new(custom_js, opts).to_s - end - - # - # Returns the heaplib2 javascript - # - def js_heaplib2(custom_js = '', opts = {}) - @cache_heaplib2 ||= Rex::Exploitation::Js::Memory.heaplib2(custom_js, opts={}) - end - - def js_base64 - @cache_base64 ||= Rex::Exploitation::Js::Utils.base64 - end - - - # - # Downloads data using ajax - # - # Supported arguments: - # method => Optional. HTTP Verb (eg. GET/POST) - # path => Relative path to the file. In IE, you can actually use an URI. But in Firefox, you - # must use a relative path, otherwise you will be blocked by the browser. - # data => Optional. Data to pass to the server - # - # Example of using the ajax_download() function: - # For IE, your web server has to return this header to download binary data: - # "text/plain; charset=x-user-defined" - # - # - def js_ajax_download - @cache_ajax_download ||= Rex::Exploitation::Js::Network.ajax_download - end - - - # - # Transfers data using a POST request - # - def js_ajax_post - @cache_ajax_post ||= Rex::Exploitation::Js::Network.ajax_post - end - - # - # This function takes advantage of MSTIME's CTIMEAnimationBase::put_values function that's - # suitable for a no-spray technique. There should be an allocation that contains an array of - # pointers to strings that we control, and each string should reside in its own buffer. - # Please note newer IEs (such as IE9), no longer support SMIL, therefore this only works on - # Internet Explorer 8 or prior. Note that "mstime_malloc" also requires a rather specific - # writing style, so make sure you have the following before using: - # * You must have the following at the beginning of your HTML file: - # - # - # * You must have the following in : - # - # - # - # - # The "mstime_malloc" JavaScript function supports the following arguments: - # shellcode => The shellcode to place. - # offset => Optional. The pointer index that points to the shellcode. - # heapBlockSize => Object size. - # objId => The ID to your ANIMATECOLOR element. - # - # Example of using "js_mstime_malloc": - # - # - def js_mstime_malloc - @cache_mstime_malloc ||= Rex::Exploitation::Js::Memory.mstime_malloc - end - - # - # This heap spray technique takes advantage of MSHTML's SetStringProperty (or SetProperty) - # function to trigger allocations by ntdll!RtlAllocateHeap. It is based on Corelan's - # publication on "DEPS – Precise Heap Spray on Firefox and IE10". In IE, the shellcode - # should land at address 0x0c0d2020, as this is the most consistent location across - # various versions. - # - # The "sprayHeap" JavaScript function supports the following arguments: - # shellcode => The shellcode to spray in JavaScript. Note: Avoid null bytes. - # objId => Optional. The ID for a
HTML tag. - # offset => Optional. Number of bytes to align the shellcode, default: 0x00 - # heapBlockSize => Optional. Allocation size, default: 0x80000 - # maxAllocs => Optional. Number of allocation calls, default: 0x350 - # - # Example of using the 'sprayHeap' function: - # - # - def js_property_spray - @cache_property_spray ||= Rex::Exploitation::Js::Memory.property_spray - end - - def js_heap_spray - @cache_heap_spray ||= Rex::Exploitation::Js::Memory.heap_spray - end - - def js_explib2 - @explib2 ||= ::Rex::Exploitation::Js::Memory.explib2 - end - - def js_explib2_payload(payload="exec") - @explib2_payload ||= ::Rex::Exploitation::Js::Memory.explib2_payload(payload) - end - - def js_os_detect - @cache_os_detect ||= ::Rex::Exploitation::Js::Detect.os - end - - def js_ie_addons_detect - @cache_ie_addons_detect ||= ::Rex::Exploitation::Js::Detect.ie_addons - end - - def js_misc_addons_detect - @cache_misc_addons_detect ||= ::Rex::Exploitation::Js::Detect.misc_addons - end - - # Transmits a html response to the supplied client - # - # HTML evasions are implemented here. - def send_response_html(cli, body, headers = {}) - body = body.to_s.unpack("C*").pack("C*") - if datastore['HTML::base64'] != 'none' - case datastore['HTML::base64'] - when 'plain' - body = Rex::Text.encode_base64(body) - when 'single_pad' - body = Rex::Text.encode_base64(' ' + body) - when 'double_pad' - body = Rex::Text.encode_base64(' ' + body) - when 'random_space_injection' - body = Rex::Text.encode_base64(body) - new = '' - while (body.size > 0) - new << body.slice!(0, rand(3) + 1) + Rex::Text.rand_text(rand(5) + 1, '', " \n") - end - body = new - end - - body = 'Could not render object' - end - - if datastore['HTML::javascript::escape'] > 0 - datastore['HTML::javascript::escape'].times { - body = '' - } - end - - if [UTF_16_LE, UTF_16_BE, UTF_32_LE, UTF_32_BE, UTF_7, UTF_8].include?(datastore['HTML::unicode']) - headers['Content-Type'] = 'text/html; charset= ' + datastore['HTML::unicode'] - body = Rex::Text.to_unicode(body, datastore['HTML::unicode']) - else - # special cases - case datastore['HTML::unicode'] - when UTF_16_BE_MARKER - headers['Content-Type'] = 'text/html' - body = "\xFE\xFF" + Rex::Text.to_unicode(body, UTF_16_BE) - when UTF_7_ALL - headers['Content-Type'] = "text/html; charset=#{UTF_7}" - body = Rex::Text.to_unicode(body, UTF_7, 'all') - when UTF_NONE - # do nothing - else - raise RuntimeError, 'Invalid unicode. how did you get here?' - end - end - - send_response(cli, body, headers) - end - -end - end diff --git a/lib/msf/core/exploit/http/server/html.rb b/lib/msf/core/exploit/http/server/html.rb new file mode 100644 index 0000000000..d8e1f23fda --- /dev/null +++ b/lib/msf/core/exploit/http/server/html.rb @@ -0,0 +1,254 @@ + +module Msf + +### +# +# This module provides methods for exploiting an HTTP client by acting +# as an HTTP server. +# +### +module Exploit::Remote::HttpServer::HTML + + include Msf::Exploit::Remote::HttpServer + + UTF_NONE = 'none' + UTF_7 = 'utf-7' + UTF_7_ALL = 'utf-7-all' + UTF_8 = 'utf-8' + UTF_16_LE = 'utf-16le' + UTF_16_BE = 'utf-16be' + UTF_16_BE_MARKER = 'utf-16be-marker' + UTF_32_LE = 'utf-32le' + UTF_32_BE = 'utf-32be' + +protected + + def initialize(info = {}) + super + + register_evasion_options( + [ + # utf-8, utf-7 and utf-7-all are currently not supported by + # most browsers. as such, they are not added by default. The + # mixin supports encoding using them, however they are not + # listed in the Option. + OptEnum.new('HTML::unicode', [false, 'Enable HTTP obfuscation via unicode', UTF_NONE, [UTF_NONE, UTF_16_LE, UTF_16_BE, UTF_16_BE_MARKER, UTF_32_LE, UTF_32_BE]]), + OptEnum.new('HTML::base64', [false, 'Enable HTML obfuscation via an embeded base64 html object (IE not supported)', 'none', ['none', 'plain', 'single_pad', 'double_pad', 'random_space_injection']]), + OptInt.new('HTML::javascript::escape', [false, 'Enable HTML obfuscation via HTML escaping (number of iterations)', 0]), + ], Exploit::Remote::HttpServer::HTML) + end + + # + # Obfuscates symbols found within a javascript string. + # + # Returns an ObfuscateJS object + # + def obfuscate_js(javascript, opts) + js = Rex::Exploitation::ObfuscateJS.new(javascript, opts) + js.obfuscate + return js + end + + # + # Encrypts a given javascript string using the provided key. + # + # Returns a string containing the encrypted string and a loader + # + def encrypt_js(javascript, key) + Rex::Exploitation::EncryptJS.encrypt(javascript, key) + end + + # + # Returns the heaplib javascript, including any custom javascript supplied + # by the caller. + # + def heaplib(custom_js = '', opts = {}) + Rex::Exploitation::HeapLib.new(custom_js, opts).to_s + end + + # + # Returns the heaplib2 javascript + # + def js_heaplib2(custom_js = '', opts = {}) + @cache_heaplib2 ||= Rex::Exploitation::Js::Memory.heaplib2(custom_js, opts={}) + end + + def js_base64 + @cache_base64 ||= Rex::Exploitation::Js::Utils.base64 + end + + + # + # Downloads data using ajax + # + # Supported arguments: + # method => Optional. HTTP Verb (eg. GET/POST) + # path => Relative path to the file. In IE, you can actually use an URI. But in Firefox, you + # must use a relative path, otherwise you will be blocked by the browser. + # data => Optional. Data to pass to the server + # + # Example of using the ajax_download() function: + # For IE, your web server has to return this header to download binary data: + # "text/plain; charset=x-user-defined" + # + # + def js_ajax_download + @cache_ajax_download ||= Rex::Exploitation::Js::Network.ajax_download + end + + + # + # Transfers data using a POST request + # + def js_ajax_post + @cache_ajax_post ||= Rex::Exploitation::Js::Network.ajax_post + end + + # + # This function takes advantage of MSTIME's CTIMEAnimationBase::put_values function that's + # suitable for a no-spray technique. There should be an allocation that contains an array of + # pointers to strings that we control, and each string should reside in its own buffer. + # Please note newer IEs (such as IE9), no longer support SMIL, therefore this only works on + # Internet Explorer 8 or prior. Note that "mstime_malloc" also requires a rather specific + # writing style, so make sure you have the following before using: + # * You must have the following at the beginning of your HTML file: + # + # + # * You must have the following in : + # + # + # + # + # The "mstime_malloc" JavaScript function supports the following arguments: + # shellcode => The shellcode to place. + # offset => Optional. The pointer index that points to the shellcode. + # heapBlockSize => Object size. + # objId => The ID to your ANIMATECOLOR element. + # + # Example of using "js_mstime_malloc": + # + # + def js_mstime_malloc + @cache_mstime_malloc ||= Rex::Exploitation::Js::Memory.mstime_malloc + end + + # + # This heap spray technique takes advantage of MSHTML's SetStringProperty (or SetProperty) + # function to trigger allocations by ntdll!RtlAllocateHeap. It is based on Corelan's + # publication on "DEPS – Precise Heap Spray on Firefox and IE10". In IE, the shellcode + # should land at address 0x0c0d2020, as this is the most consistent location across + # various versions. + # + # The "sprayHeap" JavaScript function supports the following arguments: + # shellcode => The shellcode to spray in JavaScript. Note: Avoid null bytes. + # objId => Optional. The ID for a
HTML tag. + # offset => Optional. Number of bytes to align the shellcode, default: 0x00 + # heapBlockSize => Optional. Allocation size, default: 0x80000 + # maxAllocs => Optional. Number of allocation calls, default: 0x350 + # + # Example of using the 'sprayHeap' function: + # + # + def js_property_spray + @cache_property_spray ||= Rex::Exploitation::Js::Memory.property_spray + end + + def js_heap_spray + @cache_heap_spray ||= Rex::Exploitation::Js::Memory.heap_spray + end + + def js_explib2 + @explib2 ||= ::Rex::Exploitation::Js::Memory.explib2 + end + + def js_explib2_payload(payload="exec") + @explib2_payload ||= ::Rex::Exploitation::Js::Memory.explib2_payload(payload) + end + + def js_os_detect + @cache_os_detect ||= ::Rex::Exploitation::Js::Detect.os + end + + def js_ie_addons_detect + @cache_ie_addons_detect ||= ::Rex::Exploitation::Js::Detect.ie_addons + end + + def js_misc_addons_detect + @cache_misc_addons_detect ||= ::Rex::Exploitation::Js::Detect.misc_addons + end + + # Transmits a html response to the supplied client + # + # HTML evasions are implemented here. + def send_response_html(cli, body, headers = {}) + body = body.to_s.unpack("C*").pack("C*") + if datastore['HTML::base64'] != 'none' + case datastore['HTML::base64'] + when 'plain' + body = Rex::Text.encode_base64(body) + when 'single_pad' + body = Rex::Text.encode_base64(' ' + body) + when 'double_pad' + body = Rex::Text.encode_base64(' ' + body) + when 'random_space_injection' + body = Rex::Text.encode_base64(body) + new = '' + while (body.size > 0) + new << body.slice!(0, rand(3) + 1) + Rex::Text.rand_text(rand(5) + 1, '', " \n") + end + body = new + end + + body = 'Could not render object' + end + + if datastore['HTML::javascript::escape'] > 0 + datastore['HTML::javascript::escape'].times { + body = '' + } + end + + if [UTF_16_LE, UTF_16_BE, UTF_32_LE, UTF_32_BE, UTF_7, UTF_8].include?(datastore['HTML::unicode']) + headers['Content-Type'] = 'text/html; charset= ' + datastore['HTML::unicode'] + body = Rex::Text.to_unicode(body, datastore['HTML::unicode']) + else + # special cases + case datastore['HTML::unicode'] + when UTF_16_BE_MARKER + headers['Content-Type'] = 'text/html' + body = "\xFE\xFF" + Rex::Text.to_unicode(body, UTF_16_BE) + when UTF_7_ALL + headers['Content-Type'] = "text/html; charset=#{UTF_7}" + body = Rex::Text.to_unicode(body, UTF_7, 'all') + when UTF_NONE + # do nothing + else + raise RuntimeError, 'Invalid unicode. how did you get here?' + end + end + + send_response(cli, body, headers) + end + +end + +end + diff --git a/lib/msf/core/exploit/http/php_include.rb b/lib/msf/core/exploit/http/server/php_include.rb similarity index 100% rename from lib/msf/core/exploit/http/php_include.rb rename to lib/msf/core/exploit/http/server/php_include.rb