Security JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © Institut für Systemsoftware, Johannes Kepler Universität Linz Security Einführung Klassenlader Sicherheitsmanager und Berechtigungen Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 2 Sicherheitsmechanismen in Java Virtuelle Maschine fehlerhafte Arrayzugriffe fehlerhafte Casts … Klassenlader Laden von Code Byte-Code Verifikation Sicherheitsmanager-Klassen erlaubte und unerlaubte Operationen und Zugriffe Verschlüsselungsmechanismen Codesignierung Authentifikation Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 3 Security Einführung Klassenlader Sicherheitsmanager und Berechtigungen Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 4 Laden von Klassen In Java wird Code inkrementell nach Bedarf geladen Prozess des Ladens von Klassencode (veranschaulicht anhand Ausführung des Programms MyProgram): Laden des Codes in File MyProgram.class Laden von allen Klassen von Variablen und Superklassen der Klasse MyProgram Ausführung der Methode main der Klasse MyProgram Laden aller bei der Ausführung von main benötigten Klassen Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 5 Klassenlader Das Laden von Klassen wird durch ClassLoader-Objekte durchgeführt Zugriff auf ClassLoader Class clazz = Class.forName(“MyProgram“); ClassLoader loader = clazz.getClassLoader(); Standard ClassLoader! ClassLoader loader = ClassLoader.getSystemClassLoader(); ClassLoader erlaubt Klassen explizit zu laden Class myClass = loader.loadClass("mypack.MyClass"); und zu definieren byte[] classCode = ...; loader.defineClass(“MyDefinedClass“, classCode, 0, classCode.length); Setzen des Klassenladers Für einen Thread kann man ContextClassLoader setzen Thread thread = Thread.currentThread(); thread.setContextClassLoader(loader); Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz Damit werden alle Klassen für diesen Thread mit eigenem Klassenlader geladen! 6 Arten von Klassenlader Java verwendet unterschiedle Klassenlader Bootstrap-Klassenlader: lädt alle Systemklassen aus JAR-Datei rt.jar Erweiterungsklassenlader: lädt alle Erweiterungen aus Verzeichnis jre/lib/ext Systemklassenlader (besser Anwendungsklassenlader): lädt die Anwendungsklassen aus Klassenpfad (CLASSPATH) Spezielle Klassenlader: Anwendungsspezifisches Klassenlader als Spezialisierung der Standardklassenlader Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 7 Hierarchie der Klassenlader Klassenlader stehen in einer Über-/Untergeordnet-Beziehung zueinander Hierarchie zu oberst Bootstrap-Klassenlader Bootstrapklassenlader rt.jar Erweiterungsklassenlader jre/lib/ext Systemklassenlader CLASSPATH Spezifischer Klassenlader spezifisch dann Erweiterungsklassenlader dann Systemklassenlader Dann eventuell anwendungsspezifische Klassenlader Jeder Klassenlader delegiert Laden einer Klasse an übergeordneten Klassenlader und lädt die Klasse nur selber, wenn der übergeordnete scheitert Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 8 Beispiel Spezifischer Klassenlader Eigener Klassenlader als Intanz von URLClassLoader Laden von Klassen aus Plugin-JAR Plugin-JAR nicht im CLASSPATH! URL pluginUrl = new URL("file:c:/plugins.jar"); URLClassLoader pluginLoader = new URLClassLoader( new URL[] { pluginUrl }, ClassLoader.getSystemClassLoader() ); Class<?> cl = pluginLoader.loadClass("plugin1.PluginClass"); cl.getMethod("test").invoke(null); Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz übergeordnete Klassenlader 9 Beispiel: Selbstimplementierter Klassenlader Klassenlader als Spezialisierung von ClassLoader Entschlüsselung von verschlüsselten ByteCode-Dateien durch Überschreiben von Methode findClass public class CryptoClassLoader extends ClassLoader { private final String path; private final int key; public CryptoClassLoader(String path, int key) {...}Methode findClass wird von loadClass aufgerufen! @Override protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] classBytes = null; try { classBytes = loadAndDecryptClassBytes(name); } catch (IOException e) { throw new ClassNotFoundException(name); } Class<?> clazz = defineClass(name, classBytes, 0, classBytes.length); if (clazz == null ) throw new ClassNotFoundException(name); return clazz; } private byte[] loadAndDecryptClassBytes(String name) throws IOException { ... } Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 10 Eindeutigkeit von Klassen durch Klassenlader Eindeutigkeit einer Klasse ist gegeben durch: vollständigen Name, d.h. inklusive Paketnamen (z.B. java.sql.Date) und Klassenlader, durch den sie geladen wurde Dadurch ist es möglich, dass in einer VM Klassen (mit gleichem Namen) von mehreren Quellen geladen und gleichzeitig ausgeführt wird Klassen in mehreren Versionen gleichzeitig geladen sind Beispiel: Applets geladen von mehreren Sites werden durch eigene Klassenlader unterschieden Pratikum SWE 2 MyAppletClass MyAppletClass cl1:ClassLoader cl2:ClassLoader © Institut für Systemsoftware Johannes Kepler Universität Linz 11 Security Einführung Klassenlader Sicherheitsmanager und Berechtigungen Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 13 Sicherheitsmanager Sicherheitsmanager erlaubt Prüfung, ob bestimmte (potentiell gefährliche) Operationen erlaubt sind unter anderem: Zugriff (read, write) auf File Öffnen einer Socket-Verbindung Zugriff auf Systemeigenschaften Beenden der Applikation Erzeugen eines neuen Klassenladers Zugriff auf die AWT-Eventqueue Öffnen eines neuen Top-level Fensters Installation eines neuen Sicherheitsmanagers ... Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 14 Installation eines Sicherheitsmanagers Standardmäßig kein Sicherheitsmanager installiert es werden daher auch keine Prüfungen durchgeführt Installation eines SecurityManagers für eine Applikation mit System.setSecurityManager(SecurityManager sm) oder beim Start des Programms java -Djava.security.manager ... Verfügbare Sicherheitsmanager: SecurityManager: für Standardapplikationen RMISecurityManager: für RMI-Applikationen, mit Laden von Code von Remote-Sites AppletSecurity : bei Applets Eigene Sicherheitsmanager als Ableitungen von SecurityManager Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 15 Sicherheitsmodell bei Java 2 Sicherheitsrichtlinien (SecurityPolices) bilden Codequellen (code source) auf Berechitgungsmengen (permissions) ab, d.h. einer bestimmten Codequelle sind eine Menge von Berechtigungen zugeordnet Security Policy CodeSource Codequellen und Berechtigungen sind objektorientiert dargestellt PermissionCollection CodeBase Permission Certificate Permission Klassen CodeSource mit CodeBase und Certificate Klassensystem von Berechtigungsklassen (Permission) CodeSource Mengen von Berechtigungen (PersmissionCollection) CodeBase Certificate PermissionCollection Permission Permission Permission Sicherheitsrichtlinien können in Policy-Files spezifiziert werden (siehe später) Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 16 Ablauf beim Erzeugen eines ProtectionDomains 1. Laden der Klasse durch SecureClassLoader (Basisklasse aller ClassLoader) 2. Holen der Permissions aus Policy aufgrund der Codebase 3. Definieren der Klasse (defineClass) 4. Erzeugen einer ProtectionDomain für die Klasse mit CodeSource und Permissions Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 18 Operationen mit Sicherheitsprüfung Ablauf Sicherheitsprüfung Zugriff auf installierten SecurityManager über System.getSecurityManager Wenn einer installiert ist (!= null), Aufruf der entsprechenden check-Methode beim SecurityManager Die check-Methode wirft bei Nicht-Bestehen der Prüfung eine SecurityException Ausführung der eigentlichen Operation nach bestandener Prüfung public void <checkedOperation>(...) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPermission(...); } Kann SecurityException werfen!! <uncheckedOperation>(...); } public void exit(int status) { Beispiel: exit-Operation SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPermission(new RuntimePermission("exitVM."+status)); } Shutdown.exit(status); Vereinfachte Version! } Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 19 checkPermission Prüfen von Permissions mit checkPermission von SecurityManager public void checkPermission(Permission perm) Ablauf: Prüfung einer Permission p Pseudocode checkPermission(Permission p) throws SecurityException { for all classes clazz of methods on call stack { permissionColl = clazz.getProtectionDomain().getPermissions(); if (! exists q in permissionColl with q.implies(p) ) throw SecurityException(...); } // permission p granted } Für alle Klassen der Methoden am Call-Stack Zugriff auf PermissionCollection der Klasse Wenn in PermissionCollection der Klasse keine Permission q existiert, sodass die Permission q die geforderte Permission p impliziert dann wirf eine SecurityException Wenn alle Klassen von Methoden am Call-Stack Permission p haben dann Operation ok (keine Execption) Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 20 Beispiel: read von SocketInputStream Abgesicherte Methode! Stack-Trace: Pratikum SWE 2 Die Klassen aller Methoden am Stack müssen die entsprechende Permission haben! © Institut für Systemsoftware Johannes Kepler Universität Linz 21 Methode implies von Permission Jede Permission implementiert eine Methode boolean implies(Permission permission) welche überprüft, ob sie die übergebene Permission „impliziert“ Beispiele: RuntimePermission("*") impliziert RuntimePermission("ExitVM") FilePermission(“C:\temp\*“, “read“) impliziert FilePermission(“C:\temp\MyFile“, “read“) SocketPermission( “*:1024-65535", “connect”) impliziert SocketPermission “yourserver.com:1099", “connect“) Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 22 Hierarchie von Berechtigungsklassen Werden mit unterschiedliche Parametern konfiguriert! Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 23 Policy-Files Permissions werden durch Policy-Files vergeben bestehen aus einer Folge von grant-Einträgen Zuordnung von Codesource zu einer Reihe von Permissions die Codesource besteht aus einer URL für die Codebase und grant Codesource { Permission_1; Permission_2; }; grant codebase codebase-URL signedby certificate-name ... { Namen von vertrauenswürdigen Zertifikatsstellen und jede Permission ist in der Form Schlüsselwort permission ... { permission Klassenname der Permission-Klasse permission-className target action1, ...; einem berechtigunsspezifischem Zielwert (z.B. ein ... }; Verzeichnis oder eine Operation) optional einer Liste von berechtigunsspezifischen Aktionen Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 24 Beispiel eines Policy-File Alle Codesources! grant { permission permission permission permission ... }; java.lang.RuntimePermission "stopThread"; java.net.SocketPermission "localhost:1024-", "listen"; java.util.PropertyPermission "java.version", "read"; java.util.PropertyPermission "java.vendor", "read"; grant codeBase "file:${java.home}/lib/ext/*" { permission java.security.AllPermission; }; Inkl. alle Unterverzeichnisse! grant codeBase “www.ssw.uni-linz.ac.at/classes/" { permission java.net.SocketPermission “*:1024-65535", “connect"; permission java.io.FilePermission “${user.home}${/}-“, “read “, “ write “, “execute“; ... }; ... Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 25 Tabelle mit Permission-Einträgen (Auszug) Permission java.io.FilePermission Target Dateiziel iava.net.SocketPermission Socket-Ziel java.util.PropertyPermission Eigenschaftsziel java.lang.RuntimePermission createClassLoader createSecurityManager exitVM stopThread queuePrintJob ... setDefaultAuthenticator specifyStreamHandler requestPassword-Authentication showWindowWithoutWarningBanner accessClipboard acccessEventQueue listenToAllAWTEvents readDisplayPixels getPolicy, setPolicy ... java.net.NetPermission java.awt.AWTPermission java.security.SecurityPermission ... Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz Action read, write, execute, delete accept,connect, listen, resolve read, write 26 Beispiel: SecurityManager Installation eines SecurityManagers durch System.setSecurityManager(new SecurityManager()); oder beim Programmstart java -Djava.security.manager at.jku.ssw.security.Main Damit lassen sich Files nicht mehr lesen oder schreiben try (BufferedReader reader = new BufferedReader(new InputStreamReader( new FileInputStream(filename)))) { for (String line = reader.readLine(); line != null; line = reader.readLine()) { System.out.println(line); } } catch (Throwable t) { System.out.println("Unable to read file: " + t); } try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(filename, true)))) { writer.append("Hello World!\n"); } catch (Throwable t) { System.out.println("Unable to write file: " + t); } Unable to read file: java.security.AccessControlException: access denied ("java.io.FilePermission" "test.txt" "read") Unable to write file: java.security.AccessControlException: access denied ("java.io.FilePermission" "test.txt" "write") Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 27 Beispiel: SecurityManager Policy-File mit Permissions ermöglicht Zugriff grant codeBase "file:C:/.../UE03_WS/Security_Permissions_1/bin/‐" { permission java.io.FilePermission "test.txt", "read"; permission java.io.FilePermission "test.txt", "write"; }; java -Djava.security.manager -Djava.security.policy=test.policy ... Setzt Policy-File! Setzt SecurityManager! Pratikum SWE 2 © Institut für Systemsoftware Johannes Kepler Universität Linz 28