
44065d49593b57d80d0e7494bd940262.ppt
- Количество слайдов: 75
Security Aspects in Java Bytecode Engineering (Blackhat Briefings 2002, Las Vegas, Aug 01, 02) Marc Schönefeld Software-Architect schonef@acm. org
Agenda • Java Security Architecture: an Overview • The JVM: Structures and Concepts • Bytecode Basics • Bytecode (Reverse) Engineering • Applications of Bytecode (Reverse) Engineering 2
Java Security Architecture: an overview 3
How the court defines Java Findings of Judge Thomas Penfield Jackson, Nov. 5, 1999 • 73. The term "Java" refers to four interlocking elements. • First, there is a Java programming language with which developers can write applications. • Second, there is a set of programs written in Java that expose APIs on which developers writing in Java can rely. These programs are called the "Java class libraries. " • The third element is the Java compiler, which translates the code written by the developer into Java "bytecode. " • Finally, there are programs called "Java virtual machines, " or "JVMs" which translate Java bytecode into instructions comprehensible to the underlying operating system. 5
Java Architectural Stack EJBeans Servlets, JSP J 2 EE App-Server Applet Application Browser JRE Standalone JRE, J 2 SE Web Start Java Virtual Machine Operating System Hardware 6
The typical JVM development environment Development Javac/ jikes Dog. class Class loader Cat. py jython Cat. class Class loader Bird. j J A S M Bird. class Class loader Dog. java V E R I F I E R J V M Runtime String system class System Class loader Object system class <other> System class 7
The basic security architecture • Java security (APIs) – – (access): The Security manager (origin): Signed Codebases (behalf): Principle-based access control (JAAS) cryptography • JVM security – Class loaders – Class file verification process – JVM intrinsic security features 8
Java security Security Manager and its API • Central instance for access control as far as code is concerned • Policies define access to outer-domain ressources • Security. Manager objects instances enforce policies, throwing Security. Exceptions • By Default java programs do not have a security manager, therefor it is a good precaution to instantiate one 9
Java security Security Manager and its API • Fine-grained control to Limit access on: – – – Socket. Connections (create, accept, multicast) Thread Groups Dynamic Library Loading (JNI) Files (read, write, delete) Access to External shared ressources (printjob, clipboard) – Program control (exit, toplevelwindow) – Runtime components (member, package, classloader) 10
Java security Code Base Authentication • Java-Archives (JARs) store codebases • Proof of Origin can be be achieved by signing the jars JAR Cat. class Dog. class Bird. class hash Private key Cat. class Dog. class Bird. class sign Signed hash 11
Java security JAAS: Security based on principals • Enables login functionality – Username, password – Fingerprint –. . . • Execution permitted/denied depending on the identity who runs the code – Policy based access to functionality – Fine-grained permission handling possible 12
JVM security intrinsic features • Non-continuous memory model, distinct data areas – Java stack frames (execution state) – Method area (bytecode storage) – Garbage-collected heap (object storage) • Type-safe casting • No self-modifying code • Automated garbage-collecting disallows explicit free operation • Automatic Array bounds-checking prevents off-by-one and buffer overflow scenarios 13
JVM security Class loaders • Classloaders load a classfile as byte array into the JVM • Can load from – – file, network or dynamically generated byte array Can even compile on the fly (so Java behaves like Perl) • Security features – Establishing name spaces – Enforcing separation of trusted system library code from user-supplied code via parent-delegation 14
JVM security Verifier • Task: check loaded classfile for integrity • 4 -step process – 1 st step: structural correctness – 2 nd step: data type correctness – 3 rd step: bytecode checks – 4 th step: symbolical references management (runtime) 15
JVM security Classfile verification public class Cat { void bite (int times) {. . . } } JAVAC CA FE BA BE 00 03 00 2 D 00 13 07 00 17 12 30 11. . . bytecode assembler Class loader P A S S 1 Verifier P P A A S S 2 3 P A S S J V M 4 . class public Dog. method bite I. invokestatic seek. Victim. . end method. end class 16
The Verification Process Pass 1: Basic Structural checks • the classloader delivers byte array • Magic number = 0 x. CAFEBABE ? • Version id: 1. 1=45. 3, 1. 2=46. 0, 1. 3=47. 0, 1. 4=48. 0 • All recognized attributes need to be in proper length • The class file must not be truncated or have extra bytes at the end • The constant pool must not contain any „superficially unrecognizable information“ 17
The Verification Process Pass 2: Check Context-Pool (CP) information • final classes are not subclassed, and final methods are not overridden. • All classes (except java. lang. Object) must have a superclass. • Check constraints for CP-entries: For example, class references in the CP can be resolved via a field to a string reference in the CP. • Checking that all field references and method references in the CP must have legal names, classes, and type signature. 18
The Verification Process Pass 3 : Bytecode verification • Core part of verification • Static constraints – Checking maximal local variable count throughout control flow – Checking control-flow correctness (branch always to start of instruction, not beyond end of code) – all exception-handlers are valid (no partial overlap) –. . . • Structural constraints – Reachability : subroutines (scope), exception handlers – data-flow : Instances initialization and new objects, stack size 19
The Verification Process Pass 4: delayed checks during runtime • Verifies that currently executing class is allowed to reference the given class. • The first time an instruction calls a method, or accesses or modifies a field, the verifier checks the following: – method or field class – Method or field signature – that the currently executing method has access to the given method or field • insert „quick“ optimized instructions 20
Problems with JDK verifier Not enabled by default public class Illegal. Access 2{ public String str = "The trade secret"; public void test(){ System. out. println("Test 2: " + str); } } public class Illegal. Access{ public static void main(String args[]){ Illegal. Access 2 t 2 = new Illegal. Access 2(); System. out. println("Test 1: " + t 2. str); t 2. test(); t 2. str = "an open hint"; System. out. println("Test 1: " + t 2. str); System. exit(0); } } D: entwjavablackhat>java -classpath. Test 1: The trade secret Test 2: The trade secret Test 1: an open hint Illegal. Access 21
Problems with JDK verifier Not enabled by default public class Illegal. Access 2{ private String str = "The trade secret"; public void test(){ System. out. println("Test 2: " + str); } } public class Illegal. Access{ public static void main(String[] args){ Illegal. Access 2 t 2 = new Illegal. Access 2(); System. out. println("Test 1: " + t 2. str); t 2. test(); t 2. str = "an open hint"; System. out. println("Test 1: " + t 2. str); System. exit(0); } } Variable str now restricted, JVM should now complain access, but at least on JDK 1. 3. 1 and 1. 4. 0_01 2000 the following happens. . . 22
Problems with JDK verifier Not enabled by default D: entwjavablackhat>java Illegal. Access Test 1: The trade secret Test 2: The trade secret Test 1: an open hint D: entwjavablackhat>java -verify Illegal. Access Exception in thread "main" java. lang. Illegal. Access. Error: try to access field Illegal. Access 2. str from class Illegal. Access at Illegal. Access. main(Illegal. Access. java: 7) Only the explicit -verify flag restricts access to restricted variable „str“ ! 23
Problems with Inner classes • Inner classes can access private fields of outer classes final class Outer { private String secret = "you will never be able to read this" ; public void alter_secret(String x) { secret = x; } private String reverse. Secret() { String. Buffer b = new String. Buffer(secret); return b. reverse(). to. String(); } class Inner { private String innersecret = secret; } } private String reverseinner = reverse. Secret(); new public static void main(String[] args) { Outer outer = new Outer(); } 24
Problems with Inner classes • You can‘t access these private fields from other classes via java code, but you can with a handcrafted bytecode class new Outer dup invokespecial Outer/<init> ()V // new Outer dup // dup here to avoid local vars, take it directly from stack dup invokestatic Outer/access$000 (LOuter; )Ljava/lang/String; getstatic java/lang/System/out Ljava/io/Print. Stream; swap // correct the positions invokevirtual java/io/Print. Stream/println (Ljava/lang/String; )V invokestatic Outer/access$100 (LOuter; )Ljava/lang/String; getstatic java/lang/System/out Ljava/io/Print. Stream; swap // correct the positions invokevirtual java/io/Print. Stream/println (Ljava/lang/String; )V return 25
Other Problems with JDK verifier • SDK and JRE 1. 3. 1_01 or earlier – „A vulnerability in the Java(TM) Runtime Environment Bytecode Verifier may be exploited by an untrusted applet to escalate privileges. „ • Also some Netscape browser versions were affected 26
Problems with JDK verifier • You can check your classes with a standalone verifier • Open source solution „Justice“ supplied in Apache Jakarta project BCEL new 27
Problems with Java security What is also still missing • Checks in terms of hard and soft limits on – memory allocation – Thread activation • Excessive memory usage and threading utilization often leads to Denial of Service problems 28
The JVM: Structures and Concepts 29
JVM Internals • The architecture – JVM is an abstract concept – Sun just specified the interface – implementation details depend on specific product (SUN JDK, IBM JDK, Blackdown) • Java bytecode, the internal language – independent from CPU-type (bytecode) – Stackoriented, object-oriented, type-safe 30
Runtime view on a JVM Runtime Data storage Class loader Method Area (Classes) Heap (Objects) PC registers JVM runtime Stack Frames Native method stacks Native methods 31
Runtime data • Frame: • Saves runtime state of execution threads, therefore holds information for method execution (program counter) • All frames of a thread are managed in a stack frame 32
Runtime data • Method area – Runtime information of the class file – Type information – Constant Pool – Method information – Field information – Class static fields – Reference to the classloader of the class – Reference to reflection anchor (Class) 33
The Constant Pool • The "constant pool" is a heterogenous array of data. Each entry in the constant pool can be one of the following: – string , class or interface name , reference to a field or method , numeric value , constant String value • No other part of the class file makes specific references to strings, classes, fields, or methods. All references constants and also for names of methods and fields are via lookup into the constant pool. 34
The Class File Structure H E A D E R CONSTANTPOOL FIELDS METHODS I N T E R F A C E S ACCESS FLAGS (Final, Native, Private, Protected, . . . ) A T T R I B U T E S • You can use a classdumper like javap -c or Dump. Class to analyze these inner details 35
The Class File Format • Java class files are brought into the JVM via the classloader • The class file is basically just a plain byte array, following the rules of the byte code verifier. • All 16 -bit and 32 -bit quantities are formed by reading in two or four 8 -bit bytes, respectively, and joining them together in big-endian format. 36
Methods and Fields • The type of a field or method is indicated by a string called its signature. • Fields may have an additional attribute giving the field's initial value. • Methods have an additional CODE attribute giving the java bytecode for executing that method. 37
The CODE Attribute • maximum stack space • maximum number of local variables • The actual bytecode for executing the method. • A table of exception handlers, – start and end offset into the bytecodes, – an exception type, and – the offset of a handler for the exception 38
Bytecode Basics 39
The JVM types • JVM-Types and their prefixes – – – – Byte Short Integer Long Character Single float double float References b s i (java booleans are mapped to jvm ints!) l c f d a to Classes, Interfaces, Arrays • These Prefixes used in opcodes (iadd, astore, . . . ) 40
The JVM Instruction Mnemonics • • • Shuffling (pop, swap, dup, . . . ) Calculating (iadd, isub, imul, idiv, ineg, . . . ) Conversion (d 2 i, i 2 b, d 2 f, i 2 z, . . . ) Local storage operation (iload, istore, . . . ) Array Operation (arraylength, newarray, . . . ) Object management (get/putfield, invokevirtual, new) • Push operation (aconst_null, iconst_m 1, . . ) • Control flow (nop, goto, jsr, ret, tableswitch, . . . ) • Threading (monitorenter, monitorexit, . . . ) 41
Bytecode • Java Bytecode (JBC) are followed by zero or more bytes of additional operand information. • Table lookup instructions (tableswitch, lookupswitch) have a flexible length • The wide operation extension allows the base operations to use „large“ operands • No self-modifying code • No branching to arbitrary locations, only to beginning of instructions limited to scope of current method (enforced by verifier!) 42
Bytecode (Reverse) Engineering 43
Bytecode Engineering tools • Obfuscators – • Native compilers – • Remove/Manipulate all information that can be used for reverse engineering „Real“ compile of java bytecodes to native instructions (x 86/sparc) Build your own bytecode – – Programmatic Generation Manipulate classfiles with an API 44
Obfuscators Techniques used • Identifier Name Mangling • • • The JVM does not need useful names for Methods and Fields They can be renamed to single letter identifiers Constant Pool Name Mangling • • Decrypts constant pool entries on runtime Control flow obfuscation • • Insertion of phantom variables, stack scrambling And by relying on their default values inserting ghost branch instructions, which never execute 45
Obfuscators Problems with Obfuscation • • • Constant value Mangling implies overhead processing in extra method call of an „deobfuscatename“ method in each retrieval from constant pool Dynamic class loading may become broken as classes get new names and reflection calls like class. for. Name(„Account“) will fail because class „Account“ now known as by it‘s obfuscated name „b 16“! And: Obfuscation breaks patterns that can be recognized by JIT-engines for optimization 46
Protecting the Source Code: Native Compilers • Convert Java bytecode to C • Generate executable via normal c-build éfast execution éAdditional decompilation effort needed êLong turnaround times êEven for small java programs you get monster size executable files (67 mb source for Viva. java) from some commercial products êTransformed program may than be vulnerable to buffer overflows and off-by-ones 48
Bytecode Reverse Engineering • Decompilation – Get Source code from class files • Graphical Analysis – Rebuild the logical control flow • Disassembly – Get symbolic bytecode from class files 49
Decompilers But only one really works • Several available, – MOCHA , by Hanpeter van Vliet was the first one – JASMINE , patch of Mocha - crashed less often – JAD, the fast Java Decompiler (written in C++) by Pavel Kouznetsov is quite usable, but can also be fooled • DJ JAVA , GUI for JAD • NMI, GUI for JAD 50
Decompilers • General method of decompilation – Rebuilding control flow from class file code segment – Matching flow patterns to java language contructs – Associating constants and external references from constant pool entries – Do not redo field/method and constant pool entry mangling – Condensed constant pool entries therefore sometimes result in non-valid java identifiers in the generated source 51
Graphical Analysis Overview • All Java Classfiles (those which are obfuscated, too) have to be compliant to the JVM specification • Although Control flow is interleaved in the obfuscated class file, a graphical flow reveals most of the original control flow • The inner structures and dependencies of the methods can be discovered by graphical analysis 52
53
Graphical Analysis Tools • BCEL: Byte-Code Engineering Library – Written by to Markus Dahm – Maintained by the Apache Jakarta Project – Exposes internal structure of *. class files as java objects • ai. See: graphical visualisation tool – Cross-platform – Developed by the university of saarland – Uses graphical description language 54
Graphical Analysis Procedure • Walk thru a specific code attribute of methods in a classfile • Retrieve target instructions • Calculate control blocks • Calculate successor relationships • Rebuild control flow • Export control flow graph (CFG) as GDL • Display the GDL file for the control flow in ai. See 55
Disassembling • Javap – The disassembler from the JDK • Gnoloo – disassembler by Joshua Engel from „Programming for the JVM“ (ISBN: 0201309726) – Can be used in pair with Oolong, the corresponding assembler – Comes with a good Dump. Class tool 56
Applications of Bytecode (Reverse) Engineering 57
Build your own bytecode Tools • Javac & Javap – Included in the JDK – Shows you how to translate high language constructs to bytecode • Hex-Editor for binary patching – Ultraedit or Xemacs • Oolong/Gnoloo – Assembler and disassembler • BCEL 59
Managing the Bytecode with BCEL • BCEL comes with several tools – org. apache. bcel. util. Class 2 HTML • Generates nice HTML pages for a class – org. apache. bcel. util. Java. Wrapper • Replaces standard java interpreter to use own class loader • Lets you modify a loaded class via modify. Class method, that can be overloaded – org. apache. bcel. verifier. Graphical. Verifier • Allows you to verify your class files with verbose output 60
Binary Patching with your favorite editor • Read the output of „javap –c“ or Dump. Class • You got to know the opcodes values to find the injection point • Possibilities: – so you can blank out some unwanted code with 00 00. . (nop). . – Adjust some binary checks – For example x 9 a 0016 to x 570000 („ifne +22“ to „pop nop“) • Remember to keep the right balance on the stack 61
Sample bytecode The java source public class Viva { public static void main(String[] args) { String[] TOTD = {"Viva", "Las", "Vegas"}; for (int i = 0; i < TOTD. length; i++) { new Viva(TOTD[i]); } } public Viva(String a) { System. out. println(a. to. Upper. Case()); } } 62
Sample bytecode The disassembled Viva bytecode (Gnoloo) –I. method public static main ([Ljava/lang/String; )V. limit stack 4. limit locals 3. line 3 iconst_3 anewarray java/lang/String dup iconst_0 ldc "Viva" aastore dup iconst_1 ldc "Las" aastore dup iconst_2 ldc "Vegas" aastore_1. line 4 iconst_0 istore_2 goto l 39. line 5 l 25: new Viva dup aload_1 iload_2 aaload invokespecial Viva/<init> (Ljava/lang/String; )V pop. line 4 iinc 2 1 l 39: iload_2 aload_1 arraylength if_icmplt l 25. line 7 return 63
Sample bytecode The disassembled Viva bytecode (Gnoloo) –II. method public <init> (Ljava/lang/String; )V. limit stack 2. limit locals 2. line 8 aload_0 invokespecial java/lang/Object/<init> ()V. line 9 getstatic java/lang/System/out Ljava/io/Print. Stream; aload_1 invokevirtual java/lang/String/to. Upper. Case ()Ljava/lang/String; invokevirtual java/io/Print. Stream/println (Ljava/lang/String; )V. line 10 return. end method 64
Analysis of some obfuscator‘s work DEMO 65
Things you can only do in JBC methods that only differ in return type! . class. super. field public overload java/lang/Object static myint I static mydouble D . method static jvmoverload ()I. limit stack 3. limit locals 1 iconst_1 ireturn. end method static jvmoverload ()D. limit stack 3. limit locals 1 dconst_1 dreturn. end method public static main ([Ljava/lang/String; )V. limit stack 3. limit locals 1 invokestatic overload/jvmoverload ()I putstatic overload/myint I invokestatic overload/jvmoverload ()D putstatic overload/mydouble D return. end method. end class 66
Things you can only do in JBC methods that only differ in return type! If the decompiled source is compiled again: >javac -classpath. overload. java: 15: jvmoverload() is already defined in overload static double jvmoverload() ^ 1 error • The signatures are considered duplicate in java • But valid in java bytecode, and therefore can be used in obfuscation techniques 67
DEMO 68
Usage Patterns • Scenarios – Tools for database access – Adding dynamically Logging, profiling facilities without changing sourcecode – Verifying class files on domain boundaries (add-in to content filtering systems) – Find Frontier bugs, before they may be exploited for Do. S-attacks by calling code which crashes the JVM – Port your own language to Java bytecode 69
Java Library Holes • In JNI-based applications checking for null pointers is often given too little regard • Also the routines in the core Java Runtime classes use native code (included in jvm. dll) • But not every entry into these trusted libs is shielded appropriatly • In some cases you can force a JVM crash when pumping „null“ values to that routines 70
Frontier Bugs Sample package crashtest; import sun. dc. pr. Path. Dasher; public class Crash. Test { public Crash. Test() { Path. Dasher d = new Path. Dasher(null); } public static void main(String args[]) { Crash. Test crash. Test 1 = new Crash. Test(); } } Unexpected Signal : EXCEPTION_ACCESS_VIOLATION occurred at PC=0 x 6 d 443081 Function name=JVM_Disable. Compiler Library=H: programmeJB 6jdk 1. 3. 1jrebinhotspotjvm. dll Current Java thread: at sun. dc. pr. Path. Dasher. c. Initialize(Native Method) at sun. dc. pr. Path. Dasher. <init>(Path. Dasher. java: 48) at crashtest. Crash. Test. <init>(Crash. Test. java: 91) at crashtest. Crash. Test. main(Crash. Test. java: 98) Dynamic libraries: 0 x 00400000 - 0 x 00405000 0 x 77 F 40000 - 0 x 77 FF 0000 . . H: programmeJB 6jdk 1. 3. 1binjavaw. exe C: WINDOWSSystem 32ntdll. dll 71
Frontier Bugs Localization • This possible vulnerability may also be harmful in other tools as if they rely on JNI (native interface) classes calling to some native core (written in some appropriate language, C or C++) • Example JDK: The frontier between – java library code (rt. jar) and the – jvm (jvm. dll, libjvm. so) has official and inofficial entrypoints – The official ones are called by Native Java-routines recommended by Sun (java. *) – The inofficial are called by sun. * routines 72
Frontier Bugs Semiautomatic Detection • Traverse java runtime libraries • Procedure – Detect public classes – In the public classes detect public methods – From that filter native methods – Now you have a list containing the public entry points to the JVM library or another JNI-library • Tool: Native. Finder, which is based on BCEL 73
Frontier Bugs Semiautomatic Detection • On this list: – Start with the static class methods, they are easier to test – With the object methods, you need to know how to build such on object • In the easy case you have an default constructor • In the hard case you will have to delve deep into the class hierarchy to get an object – Then call the method with some nice „null“ values and wait 74
DEMO 75
Soon to become a problem: Hot Swap • Until JDK 1. 3 class definitions were immutable during the lifetime of a JVM • JDK 1. 4 now offers a „hot swap“ of class definitions via JVMDI (debugger API) • Now you (or someone else? ) can „substitute your class definitions by modified code in a running application through the debugger“ 76
Q&A Mail to schonef@acm. org for the tools Or visit our website http: //www. illegalaccess. org/ for some more examples and links (sept 02) 77
Thank you! To You as a great audience, To The Blackhat Staff (specially Charel for the tickets), To Halvar, Johnny and G 0 dzilla for the helpful discussions, And to my Girlfriend 78
44065d49593b57d80d0e7494bd940262.ppt