Java Security
Topics
• Intro to the Java Sandbox• Language Level Security• Run Time Security• Evolution of Security Sandbox Models• The Security Manager
Internet Security Needed
• Nowadays, code is downloaded from the Internet and executed transparently by millions of users.
• Downloaded software can hide all sorts of hazardous code. Games and music are often Trojan horses, spyware and virus installers.
• There is a real need for a more security mechanism for mobile code.
Writing Secure Code
• Software developers also have security problems to handle. Programmers unknowingly leave holes in their code that hackers can exploit. – Forgetting to deallocate resources. – An open socket connection is like an open
invitation to a hacker.– Memory leaks can be exploited– Buffer overflow
The Java Solution
• Java Virtual Machine creates a sandbox
• Syntax - insecure operations cannot even be represented
• Automatic garbage collection prevents memory leaks
• Security Manager watches for anomalies during execution and can take action
JVM
• Java is an interpreted language. Your source code is “compiled” to “bytecode” which is executed on the JVM.
• The Java Virtual Machine (JVM) observes each instruction (bytecode) before it is used.
• This allows Java to provide the idea of a sandbox, which limits how an untrusted program can affect the system it runs on.
Language Level Security
• No pointers or pointer arithmetic
• No way to represent unstructured memory
• Variables, methods and classes can be final
• Compiler checks variable instantiation and typecasts
No Pointers
• Pointers and pointer arithmetic allow attackers to access any byte in memory.
• In C, strings and arrays are essentially unstructured memory. They start with a pointer and operations on the array are done by manipulating the pointer. There is no bounds checking.
• The Java programmer cannot represent or manipulate pointers.
No Pointers
• You just can’t write a Java program to do damage like this.
void main() { int *randAddress; randAddress = (int *) rand(); *randAddress = rand();}
No Unstructured Memory Access
• Unstructured memory access (or unenforced structure) can be exploited.
• In C and C++, character data can be written to memory allocated as integer. Character or integer data can be read and interpreted as Boolean.
• Java prevents data of one type from being used as a different type – cannot be expressed in bytecode.
Unspecified Memory Layout
• The JVM stores several types of data to execute a program– Runtime stacks – one for each thread– Bytecode for methods– Dynamic memory heap and garbage
collection area
• The storage layout is not defined for the JVM. Each implementation does it differently.
The Keyword final
• This keyword can be used to prevent variables, methods and classes from being changed (and potentially exploited).
• The value of a variable is fixed for the duration of the execution.
• A method cannot be modified in subclasses (hacker tactic to use permission levels of original method)
• Class cannot have subclasses (subclass of API would have full system access).
The Compiler
• The compiler checks code and produces bytecode (intermediate representation interpreted by all JVMs).
• Checks that: – variables are instantiated before they are
used.– Type casts are legal (prevents unstructured
memory exploits)– Methods called by appropriate type objects
Run-time security
• Java Virtual Machine – the runtime environment – Bytecode verifier, class loader, runtime
checks– Sandbox evolution– Security manager
Bytecode Verifier, Class Loader
• Bytecode verifier runs first and guards against circumvention of compiler checks with handwritten bytecode.
• Class loader checks permissions and helps to prevent the loading of “Trojan Horse” methods.
Run Time Checks
• Bounds checking on arrays (no buffer overflow)
• Type cast checking
• Automatic garbage collection (memory leaks can lead to DOS attacks
The Sandbox Idea
• The original Java release, jdk1.0, provided a system that used the basic sandbox model.
• Differentiated only between native code (code stored locally, trusted, given full access) and non-native code (applets downloaded, not trusted).
JDK 1.0 Sandbox
• Trusted code can read, write and delete any file, start and kill threads and open, use and close socket connections without any restrictions.
• Untrusted code cannot access any files, threads are hidden and only socket connections to the applet’s origin server are allowed.
JDK 1.1: More Flexible
• Native code is trusted and treated as in JDK1.0
• Non-native code can be trusted or non-trusted.– If the .jar file has a valid digital signature and
comes from a “trusted developer” (list is part of the JVM) code is considered trusted and given same rights as native code.
– Otherwise, untrusted and restrictions apply.
JDK 1.2
• ALL code (even native) is subject to a security policy that can be defined by the user.
• Permissions are checked against the policy when the class is loaded AND whenever restricted actions are attempted.
• Promotes Principle of Least Priviledge
• Performs Complete Mediation
JDK 1.2 Restricted Actions• Accept a socket connection• Open a socket connection• Wait for a connection on a port• Create a new process• Modify a thread• Cause the application to exit• Load a dynamic library that contains native methods• Access or modify system properties• Read from a file• Write to a file• Delete a file• Create a new class loader• Load a class from a specified package• Add a new class to a specified package
The Security Manager
• The part of the JVM that performs these run time checks is called the security manager
• JDK 1.2 or later (a.k.a. Access Manager)
• In addition the security manager watches other potential security holes and can react if needed.
Possible Problems
• Security features not automatic if Java program is invoked on the command line
• And others as yet undiscovered …
Readings
• http://java.sun.com/sfaq
• http://www.javaworld.com/javaworld/jw-08-1997/jw-08-hood_p.html