Lecture 20: Hair Dryer Attacks Image from www.clean-funny.com, GoldenBlue LLC. CS201j: Engineering Software University of Virginia Computer Science David Evans http://www.cs.virginia.edu/evans Menu • Array Subtyping • Java Security Review • Violating Type Safety with a Hair Dryer 6 November 2003 CS 201J Fall 2003 2 Subtyping and Arrays If B <= A, should B[] <= A []? 6 November 2003 CS 201J Fall 2003 3 Array Subtyping static public Object getFirst (Object [] els) throws NoSuchElementException { if (els == null || els.length == 0) { throw new NoSuchElementException (); } else { return els[0]; } } static public void main (String args[]) { try { Object o = getFirst (args); System.err.println ("The first parameter is: " + o); } catch (NoSuchElementException e) { System.err.println ("There are no parameters!"); } } 6 November 2003 CS 201J Fall 2003 4 Array Store static public void setFirst (Object [] els) throws NoSuchElementException { if (els == null || els.length == 0) { throw new NoSuchElementException (); } else { els[0] = new Object (); } > javac TestArrays.java } > java TestArrays test The first parameter is: test Exception in thread "main" java.lang.ArrayStoreException at TestArrays.setFirst(TestArrays.java:16) at TestArrays.main(TestArrays.java:25) static public void main (String args[]) { try { Object o = getFirst (args); System.err.println ("The first parameter is: " + o); setFirst (args); } catch (NoSuchElementException e) { System.err.println ("There are no parameters!"); } }6 November 2003 CS 201J Fall 2003 5 ESC/Java and Array Stores > escjava TestArrays.java ESC/Java version 1.2.4, 27 September 2001 TestArrays ... TestArrays: getFirst(java.lang.Object[]) ... [0.199 s] passed TestArrays: setFirst(java.lang.Object[]) ... -----------------------------------------------------------------------TestArrays.java:16: Warning: Type of right-hand side possibly not a subtype of array element type (ArrayStore) els[0] = new Object (); 6 November 2003 CS 201J Fall 2003 6 Java • Type checking: B <= A B[] <= A[] • Need a run-time check for every array store (to an array where the actual element type is not known) • Better rule: no inference of array subtypes 6 November 2003 CS 201J Fall 2003 7 Java Security 6 November 2003 CS 201J Fall 2003 8 Java malcode.java javac Compiler malcode.class JVML Trusted Computing Base Java Bytecode Verifier Invalid “Okay” STOP JavaVM Joe User 6 November 2003 CS 201J Fall 2003 9 Bytecode Verifier • Checks JVML code satisfies safety properties – Simulates program execution to know types are correct, but doesn’t need to examine any instruction more than once – After code is verified, it is trusted: is not checked for type safety at run time (except for casts, array stores) Key assumption: when a value is written to a memory location, the value in that memory location is the same value when it is read. 6 November 2003 CS 201J Fall 2003 10 Violating the Assumption … // The object on top of the stack is a SimObject astore_0 // There is a SimObject in location 0 aload_0 // The value on top of the stack is a SimObject If a cosmic ray hits the right bit of memory, between the store and load, the assumption might be wrong. 6 November 2003 CS 201J Fall 2003 11 Improving the Odds • Set up memory so that a single bit error is likely to be exploitable • Mistreat the hardware memory to increase the odds that bits will flip Following slides adapted (with permission) from Sudhakar Govindavajhala and Andrew W. Appel, Using Memory Errors to Attack a Virtual Machine, July 2003. 6 November 2003 CS 201J Fall 2003 12 Making Bit Flips Useful Fill up memory with Filler objects, and one Pointee object: class Filler { Pointee a1; Pointee a2; Pointee a3; Pointee a4; Pointee a5; Pointee a6; Pointee a7; } 6 November 2003 class Pointee { Pointee a1; Pointee a2; Filler f; int b; Pointee a5; Pointee a6; Pointee a7; } CS 201J Fall 2003 13 a1 a3 a4 a5 Pointee p = new Pointee (); Vector fillers = new Vector (); try { while (true) { Filler f = new Filler (); f.a1 = p; f.a2 = p; f.a3 = p; …; f.a7 =p; fillers.add (f); } } catch (OutOfMemoryException e) { ; } a6 a7 a1 a2 f b a5 Pointee Object Filling Up Memory Filler Object a2 a6 a7 a1 Filler Object 6 November 2003 CS 201J Fall 2003 a2 a3 a4 14 a1 Wait for a bit flip… a3 a4 • Remember: there are lots of Filler objects (fill up all of memory) • If a bit flips, good chance (~70%) it will be in a field of a Filler object and it will now point to a Filler object instead of a Pointee object a5 a6 a7 a2 f b a5 CS 201J Fall 2003 Pointee Object a1 a6 a7 a1 Filler Object 6 November 2003 Filler Object a2 a2 a3 a4 15 a1 Type Violation a3 a4 a5 After the bit flip, the value of f.a2 is a Filler object, but f.a2 was declared as a Pointee object! Filler Object a2 a6 a7 a2 f b a5 Pointee Object a1 a6 a7 Can we exploit this? a1 Filler Object 6 November 2003 CS 201J Fall 2003 a2 a3 a4 16 Pointee p = new Pointee (); Vector fillers = new Vector (); try { while (true) { Filler f = new Filler (); f.a1 = p; f.a2 = p; f.a3 = p; …; f.a7 =p; fillers.add (f); } } catch (OutOfMemoryException e) { ; } Finding the Bit Flip while (true) { for (Enumeration e = fillers.elements (); e.hasMoreElements () ; ) { Filler f = (Filler) e.nextElement (); if (f.a1 != p) { // bit flipped! … } else if (f.a2 != p) { … } } 6 November 2003 CS 201J Fall 2003 17 Violating Type Safety class Filler { Pointee a1; Pointee a2; Pointee a3; Pointee a4; Pointee a5; Pointee a6; Pointee a7; } class Pointee { Pointee a1; Pointee a2; Filler f; int b; Pointee a5; Pointee a6; Pointee a7; } Filler f = (Filler) e.nextElement (); if (f.a1 != p) { // bit flipped! Object r = f.a1; // Filler fr = (Filler) r; // Cast is checked at run-time f.a1 f.a1.b fr == f.a1 fr.a4 == f.a1.b 6 November 2003 Declared Type Pointee int Filler Pointee CS 201J Fall 2003 18 Violating Type Safety class Filler { Pointee a1; Pointee a2; Pointee a3; Pointee a4; Pointee a5; Pointee a6; Pointee a7; } class Pointee { Pointee a1; Pointee a2; Filler f; int b; Pointee a5; Pointee a6; Pointee a7; } Filler f = (Filler) e.nextElement (); if (f.a1 != p) { // bit flipped! Object r = f.a1; // Filler fr = (Filler) r; // Cast is checked at run-time f.a1.b = 69473248; // Address of bank balance object fr.a4.a1 = p.a5; // Set it to a new value 6 November 2003 CS 201J Fall 2003 19 Violating Type Safety class Filler { Pointee a1; Pointee a2; Pointee a3; Pointee a4; Pointee a5; Pointee a6; Pointee a7; } class Pointee { Pointee a1; Pointee a2; Filler f; int b; Pointee a5; Pointee a6; Pointee a7; } Filler f = (Filler) e.nextElement (); if (f.a1 != p) { // bit flipped! Object r = f.a1; // Filler fr = (Filler) r; // Cast is checked at run-time f.a1.b = 1524383; // Address of the SecurityManager fr.a4.a1 = null; // Set it to a null // Do whatever you want! There’s no security policy now… new File (“C:\thesis.doc”).delete (); 6 November 2003 CS 201J Fall 2003 20 Getting a Bit Flip • Wait for a Cosmic Ray – You have to be really, really patient… (or move machine out of Earth’s atmosphere) • X-Rays – Expensive, not enough power to generate bit-flip • High energy protons and neutrons – Work great - but, you need a particle accelerator • Hmm…. 6 November 2003 CS 201J Fall 2003 21 Using Heat 50-watt spotlight bulb Between 80° 100°C, memory starts to have a few failures Attack applet is successful (at least half the time)! Hairdryer works too, but it fries too many bits at once Picture from Sudhakar Govindavajhala 6 November 2003 CS 201J Fall 2003 22 Should Anyone be Worried? Java virtual machine 6 November 2003 CS 201J Fall 2003 23 Recap • Verifier assumes the value you write is the same value when you read it • By flipping bits, we can violate this assumption • By violating this assumption, we can violate type safety: get two references to the same storage that have inconsistent types • By violating type safety, we can get around all other security measures • For details, see paper linked from notes 6 November 2003 CS 201J Fall 2003 24 Charge: Problem Set 6 • Violate type safety to steal an election • No need to open up ITC machines to try to heat up memory – Please don’t try this in lab (but try it at home if you want) • Instead, use java –noverify to get around type checking: allows byte codes to run without verifying them 6 November 2003 CS 201J Fall 2003 25