Module: Msf::Exploit::Remote::HttpServer::HTML

Includes:
Msf::Exploit::Remote::HttpServer
Included in:
BrowserExploitServer
Defined in:
lib/msf/core/exploit/remote/http_server/html.rb

Overview

This module provides methods for exploiting an HTTP client by acting as an HTTP server.

Constant Summary collapse

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'

Instance Attribute Summary

Attributes included from SocketServer

#service

Instance Method Summary collapse

Methods included from Msf::Exploit::Remote::HttpServer

#add_resource, #add_robots_resource, #autofilter, #check_dependencies, #cleanup, #cli, #cli=, #close_client, #create_response, #fingerprint_user_agent, #get_resource, #get_uri, #hardcoded_uripath, #on_request_uri, #print_prefix, #random_uri, #regenerate_payload, #remove_resource, #report_user_agent, #resource_uri, #send_local_redirect, #send_not_found, #send_redirect, #send_response, #send_robots, #srvhost_addr, #srvport, #start_service, #use_zlib

Methods included from Auxiliary::Report

#active_db?, #create_cracked_credential, #create_credential, #create_credential_and_login, #create_credential_login, #db, #db_warning_given?, #get_client, #get_host, #inside_workspace_boundary?, #invalidate_login, #mytask, #myworkspace, #myworkspace_id, #report_auth_info, #report_client, #report_exploit, #report_host, #report_loot, #report_note, #report_service, #report_vuln, #report_web_form, #report_web_page, #report_web_site, #report_web_vuln, #store_cred, #store_local, #store_loot

Methods included from Metasploit::Framework::Require

optionally, optionally_active_record_railtie, optionally_include_metasploit_credential_creation, #optionally_include_metasploit_credential_creation, optionally_require_metasploit_db_gem_engines

Methods included from TcpServer

#on_client_close, #on_client_connect, #ssl, #ssl_cert, #ssl_cipher, #ssl_compression, #start_service

Methods included from SocketServer

#_determine_server_comm, #cleanup, #exploit, #on_client_data, #primer, #regenerate_payload, #srvhost, #srvport, #start_service, #stop_service, #via_string_for_ip

Instance Method Details

#encrypt_js(javascript, key) ⇒ Object (protected)

Encrypts a given javascript string using the provided key.

Returns a string containing the encrypted string and a loader


57
58
59
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 57

def encrypt_js(javascript, key)
  Rex::Exploitation::EncryptJS.encrypt(javascript, key)
end

#heaplib(custom_js = '', opts = {}) ⇒ Object (protected)

Returns the heaplib javascript, including any custom javascript supplied by the caller.


65
66
67
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 65

def heaplib(custom_js = '', opts = {})
  Rex::Exploitation::HeapLib.new(custom_js, opts).to_s
end

#initialize(info = {}) ⇒ Object (protected)


26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 26

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

#js_ajax_downloadObject (protected)

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>

99
100
101
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 99

def js_ajax_download
  @cache_ajax_download ||= Rex::Exploitation::Js::Network.ajax_download
end

#js_ajax_postObject (protected)

Transfers data using a POST request


107
108
109
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 107

def js_ajax_post
  @cache_ajax_post ||= Rex::Exploitation::Js::Network.ajax_post
end

#js_base64Object (protected)


76
77
78
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 76

def js_base64
  @cache_base64 ||= Rex::Exploitation::Js::Utils.base64
end

#js_explib2Object (protected)


176
177
178
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 176

def js_explib2
  @explib2 ||= ::Rex::Exploitation::Js::Memory.explib2
end

#js_explib2_payload(payload = "exec") ⇒ Object (protected)


180
181
182
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 180

def js_explib2_payload(payload="exec")
  @explib2_payload ||= ::Rex::Exploitation::Js::Memory.explib2_payload(payload)
end

#js_heap_sprayObject (protected)


172
173
174
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 172

def js_heap_spray
  @cache_heap_spray ||= Rex::Exploitation::Js::Memory.heap_spray
end

#js_heaplib2(custom_js = '', opts = {}) ⇒ Object (protected)

Returns the heaplib2 javascript


72
73
74
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 72

def js_heaplib2(custom_js = '', opts = {})
  @cache_heaplib2 ||= Rex::Exploitation::Js::Memory.heaplib2(custom_js, opts={})
end

#js_ie_addons_detectObject (protected)


188
189
190
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 188

def js_ie_addons_detect
  @cache_ie_addons_detect ||= ::Rex::Exploitation::Js::Detect.ie_addons
end

#js_misc_addons_detectObject (protected)


192
193
194
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 192

def js_misc_addons_detect
  @cache_misc_addons_detect ||= ::Rex::Exploitation::Js::Detect.misc_addons
end

#js_mstime_mallocObject (protected)

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>

142
143
144
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 142

def js_mstime_malloc
  @cache_mstime_malloc ||= Rex::Exploitation::Js::Memory.mstime_malloc
end

#js_os_detectObject (protected)


184
185
186
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 184

def js_os_detect
  @cache_os_detect ||= ::Rex::Exploitation::Js::Detect.os
end

#js_property_sprayObject (protected)

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>

168
169
170
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 168

def js_property_spray
  @cache_property_spray ||= Rex::Exploitation::Js::Memory.property_spray
end

#obfuscate_js(javascript, opts) ⇒ Object (protected)

Obfuscates symbols found within a javascript string.

Returns an ObfuscateJS object


46
47
48
49
50
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 46

def obfuscate_js(javascript, opts)
  js = Rex::Exploitation::ObfuscateJS.new(javascript, opts)
  js.obfuscate
  return js
end

#send_response_html(cli, body, headers = {}) ⇒ Object (protected)

Transmits a html response to the supplied client

HTML evasions are implemented here.


199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/msf/core/exploit/remote/http_server/html.rb', line 199

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