Language such as C++, C could give you a lot trouble in security.
It is all or nothing, once you get a hold of a pointer. You can do arithmetic, walk with it freely in memory. Well, do anything.
Java as a "secure" language. Has a lot of build-in Language-Level Security
No manual hard code of delete or free of memory
When no reference is attached to a piece of memory, the Java garbage collector release the memory
Freed memory rejoin the free storage pool, and can be used by another program
In JRE 1.2, there is no asynchronous running of garbage collector
There is also no turning off of the collector
Stack memory allocation is also in Java.
Multiple per program with each executing thread per stack
Only local variables of a method are allocated in the stack
No pointer arithmetic
Clearly defines behavior to uninitialized variables
All heap-based memory is automatically initialized
All stack-based memory is not
Thus, all class and instance variables are never set to undefined values
All local variables must definitely be assigned before use or the source compiler is obligated to give you an error
Strong (than C++) compile-time type-checking
Cannot cast object back and for like C++
final modifier which disallows subclassing and overriding
If final is applied to object, then it cannot later point to another object (no changing)
There is a concept called blank finals. Make all the data member in a class final. Then build the constructor to initize the data member (for every constructor). Thus, the member field cannot be accidentially altered after the object has been constructed.
JVM is the secure sandbox
JVM verifies all classes in the sandbox
It is a fense to prevent unwanted access to the outside (e.g. the OS JVM runs on)
The best you can do is denial-of-service that take 100% of CPU
The machine language for JVM
Cross compilers exist besides Java. For example, Ada, COBOL, etc.
When class is loaded, the first thing is JVM inspecting validity of Java byte codes
Four pass process in verification
1. Checking magic number, the first four bytes of the file are 0x CAFEBABE
2. Check superclass is not Object
3. Code verification to ensure opcodes are still valid. Make sure method arguments are proper type and opcode arguments are right
4. Performed when a method is invoked. Verifiy member access with public protected, default, or private
In JDK 1.2, only class loaded over the network is checked
"Can't find class" error would be found
ClassLoader finds and loads the class
ClassLoader will not load any class in java.* package (the core libraries classes). No false representation of the core
Separate name space for classes from different locations (could have the same class name)
Different location classes would not communicate. Untrusted programs cannot get info from trusted programs
loadClass concept
// within loadClass() Class c = findLoadedClass (name); if (c == null) { try { // If cannot load the class, find it c = findSystemClass (name); } catch (Exception e) { // Ignore these exceptions. } } if (c == null) { // User defined loadClassData, get it from database, network, etc byte data[] = loadClassData(name); // Covert byte into a class c = defineClass (name, data, 0, data.length); if (c == null) throw new ClassNotFoundException (name); if (resolve) resolveClass (c); } return c;
import java.io.*; import java.net.*; import java.util.*; // // Example for loading a class from a file // public class FileClassLoader extends ClassLoader { private String root; public FileClassLoader (String rootDir) { if (rootDir == null) throw new IllegalArgumentException ("No file directory provided"); root = rootDir; } protected Class loadClass (String name, boolean resolve) throws ClassNotFoundException { // Since all support classes of loaded class use same class loader // must check subclass cache of classes for things like Object Class c = findLoadedClass (name); if (c == null) { try { c = findSystemClass (name); } catch (Exception e) { // Do nothing if system class is not the one } } if (c == null) { // Convert class name argument to filename // Convert package names into subdirectories String filename = name.replace ('.', File.separatorChar) + ".class"; try { byte data[] = loadClassData(filename); c = defineClass (name, data, 0, data.length); if (c == null) throw new ClassNotFoundException (name); } catch (IOException e) { throw new ClassNotFoundException ("Error reading file: " + filename); } } if (resolve) resolveClass (c); return c; } private byte[] loadClassData (String filename) throws IOException { // Create a file object relative to directory provided File f = new File (root, filename); System.out.println("INFO: rootdir is [" + root + "]"); // Get size of class file int size = (int)f.length(); // Reserve space to read byte buff[] = new byte[size]; // Get stream to read from FileInputStream fis = new FileInputStream(f); DataInputStream dis = new DataInputStream (fis); // Read in data dis.readFully (buff); // close stream dis.close(); // return data return buff; } }
public class CLTester { public static void main (String args[]) throws Exception { FileClassLoader loader = new FileClassLoader(args[0]); // Load the class with my own file Class c = loader.loadClass (args[1]); Object tester = c.newInstance(); } }
java CLTester C:\sinn\Java\security\classloader\testdir Tester
import java.net.*; import java.io.*; // Indicate the location of the class to load public class URLTester { public static void main (String args[]) throws Exception { // Create an array of URLs // From directory name specified as args[0] URL urlList[] = {new File(args[0]).toURL()}; // Create a URLClassLoader ClassLoader loader = new URLClassLoader(urlList); // Load class from class loader // Use args[1] as class name Class c = loader.loadClass (args[1]); // Create an instance of the class just loaded Object tester = c.newInstance(); } }
java URLTester C:\sinn\Java\security\classloader\testdir Tester
Most type-checking can be done at compile time
Sometimes type of an object can only be found out in runtime
JVM ensure that for example, subclass cannot access data specifically defined for superclass
JVM also ensures you do not try to pass off something that is not part of the class hierarchy as one of its own
ArrayIndexOutOfBoundsException is thown when walking pass from an array
Security Manager
Each instance of JVM has a SecurityManager
Once a manager is installed, it cannot be replaced
Replacement will cause SecurityException to be thrown
SecurityManager provides a "hard coded" security policy
E.g. browser's security manager prevents applets loaded over the network read or write files in local file system
For every operations, the Java program checks with the SecurityManager to see if the operation is allowed or not
SecurityException thrown if fails. It is a RuntimeException, so try catch block is not needed
import java.io.*; public class SMTester { public static void main (String args[]) { try { File f = new File("joe.txt"); System.out.println ("joe.txt exists? " + f.exists()); } catch (SecurityException e) { System.err.println ("Cannot check if joe.txt exists"); } System.setSecurityManager(new MySecurityManager()); System.out.println ("\nAfter new SM Installed\n"); // After the new security manager is loaded // only .tmp extension can be checked. (To show as a demo) try { File f = new File("joe.txt"); System.out.println ("joe.txt exists? " + f.exists()); } catch (SecurityException e) { System.err.println ("Cannot check if joe.txt exists"); } try { File f = new File("joe.tmp"); System.out.println ("joe.tmp exists? " + f.exists()); } catch (SecurityException e) { System.err.println ("Cannot check if joe.tmp exists"); } try { File f = new File("joe.txt"); System.out.println ("joe.txt writable? " + f.canWrite()); } catch (SecurityException e) { System.err.println ("Cannot check if joe.txt writable"); } try { File f = new File("joe.tmp"); System.out.println ("joe.tmp writable? " + f.canWrite()); } catch (SecurityException e) { System.err.println ("Cannot check if joe.tmp writable"); } } }
import java.io.*; import java.net.*; class NullSecurityManager extends SecurityManager { public void checkCreateClassLoader() { } public void checkAccess(Thread g) { } public void checkAccess(ThreadGroup g) { } public void checkExit(int status) { } public void checkExec(String cmd) { } public void checkLink(String lib) { } public void checkRead(FileDescriptor fd) { } public void checkRead(String file) { } public void checkRead(String file, Object context) { } public void checkWrite(FileDescriptor fd) { } public void checkWrite(String file) { } public void checkDelete(String file) { } public void checkConnect(String host, int port) { } public void checkConnect(String host, int port, Object context) { } public void checkListen(int port) { } public void checkAccept(String host, int port) { } public void checkMulticast(InetAddress maddr) { } public void checkMulticast(InetAddress maddr, byte ttl) { } public void checkPropertiesAccess() { } public void checkPropertyAccess(String key) { } public void checkPropertyAccess(String key, String def) { } public boolean checkTopLevelWindow(Object window) { return true; } public void checkPrintJobAccess() { } public void checkSystemClipboardAccess() { } public void checkAwtEventQueueAccess() { } public void checkPackageAccess(String pkg) { } public void checkPackageDefinition(String pkg) { } public void checkSetFactory() { } public void checkMemberAccess(Class clazz, int which) { } public void checkSecurityAccess(String provider) { } }
import java.io.*; public class MySecurityManager extends NullSecurityManager { // Only check file with .tmp extension final static String filenameEnding = ".tmp"; public void checkRead(String file) { if (!file.endsWith(filenameEnding)) { throw new SecurityException ("My exception: Read attempt: " + file); } } public void checkRead(String file, Object context) { checkRead (file); } public void checkWrite(String file) { if (!file.endsWith(filenameEnding)) { throw new SecurityException ("My exception: Write attempt: " + file); } } }
> java SMTester joe.txt exists? false After new SM Installed Cannot check if joe.txt exists joe.tmp exists? false Cannot check if joe.txt writable joe.tmp writable? false