Last active
January 3, 2016 23:22
-
-
Save beargiles/0bc3c741b51c295d67a9 to your computer and use it in GitHub Desktop.
SecurityManager example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.invariantproperties.sandbox.securityManager; | |
import java.net.InetSocketAddress; | |
import java.net.SocketPermission; | |
import java.security.Permission; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.List; | |
/** | |
* Security manager that blocks DNS queries. This will block certain | |
* types of data exfiltration. | |
* | |
* @author bgiles | |
*/ | |
public class DnsBlockingSecurityManager extends SecurityManager { | |
private final SecurityManager parent; | |
private final List<String> whitelist = new ArrayList<>(); | |
public DnsBlockingSecurityManager() { | |
this(null); | |
} | |
public DnsBlockingSecurityManager(SecurityManager parent) { | |
this.parent = parent; | |
// we can read a configuration file to get a list of | |
// acceptable DNS servers. | |
} | |
@Override | |
public void checkPermission(Permission perm) { | |
if (parent != null) { | |
parent.checkPermission(perm); | |
} | |
if (perm instanceof SocketPermission) { | |
SocketPermission sp = (SocketPermission) perm; | |
List<String> actions = Arrays.asList(sp.getActions().split(",")); | |
if (actions.contains("connect")) { | |
String name = sp.getName(); | |
if (!name.matches("[a-zA-Z0-9_\\.]+:[0-9]+")) { | |
throw new SecurityException("unexpected socket addr format"); | |
} | |
String[] elements = sp.getName().split(":"); | |
InetSocketAddress addr = new InetSocketAddress(elements[0], Integer.valueOf(elements[1])); | |
if (addr.getPort() == 53 && !whitelist.contains(addr.getHostName())) { | |
throw new SecurityException("DNS connections are not allowed to this host"); | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.invariantproperties.sandbox.securityManager; | |
import java.io.PrintStream; | |
import java.security.Permission; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.HashSet; | |
import java.util.List; | |
import java.util.Set; | |
/** | |
* Simple SecurityManager that does nothing but log requests. | |
* | |
* @author bgiles | |
*/ | |
public class LoggingSecurityManager extends SecurityManager { | |
private final Set<String> permissions = new HashSet<>(); | |
/** | |
* List permissions required since last time. Reset set of permissions. | |
* | |
* @param ps | |
*/ | |
public void listPermissions(PrintStream ps) { | |
List<String> list = new ArrayList<String>(permissions); | |
Collections.sort(list); | |
for (String entry : list) { | |
ps.println(entry); | |
} | |
permissions.clear(); | |
} | |
public void checkPermission(Permission perm) { | |
permissions.add(perm.toString()); | |
} | |
public void checkPermission(Permission perm, Object obj) { | |
permissions.add(perm.toString() + ": " + obj); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/i386/libnet.so" "read") | |
("java.lang.RuntimePermission" "loadLibrary.net") | |
("java.net.SocketPermission" "8.8.8.8:53" "accept,resolve") | |
("java.net.SocketPermission" "8.8.8.8:53" "connect,resolve") | |
("java.net.SocketPermission" "localhost:0" "listen,resolve") | |
("java.util.PropertyPermission" "impl.prefix" "read") | |
("java.util.PropertyPermission" "os.name" "read") | |
("java.util.PropertyPermission" "sun.net.maxDatagramSockets" "read") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
("java.io.FilePermission" "/dev/random" "read") | |
("java.io.FilePermission" "/dev/urandom" "read") | |
("java.io.FilePermission" "/etc/java-8-openjdk/net.properties" "read") | |
("java.io.FilePermission" "/tmp/nothing-1388226371259550611.html" "delete") | |
("java.io.FilePermission" "/tmp/nothing-1388226371259550611.html" "write") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/classes" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/charsets.jar" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/ext/i386/libsunec.so" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/ext/libsunec.so" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/ext/sunec.jar" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/ext/sunjce_provider.jar" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/i386/libnet.so" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/i386/libnio.so" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/i386/libsunec.so" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/jce.jar" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/jfr.jar" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/jsse.jar" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/meta-index" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/resources.jar" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/rt.jar" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/security/US_export_policy.jar" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/security/blacklisted.certs" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/security/cacerts" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/security/jssecacerts" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/security/local_policy.jar" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/lib/sunrsasign.jar" "read") | |
("java.io.FilePermission" "/usr/lib/jvm/java-8-openjdk-i386/jre/meta-index" "read") | |
("java.lang.RuntimePermission" "accessClassInPackage.sun.security.action") | |
("java.lang.RuntimePermission" "accessClassInPackage.sun.security.ec") | |
("java.lang.RuntimePermission" "accessClassInPackage.sun.security.internal.interfaces") | |
("java.lang.RuntimePermission" "accessClassInPackage.sun.security.internal.spec") | |
("java.lang.RuntimePermission" "accessClassInPackage.sun.security.pkcs") | |
("java.lang.RuntimePermission" "accessClassInPackage.sun.security.provider") | |
("java.lang.RuntimePermission" "accessClassInPackage.sun.security.rsa") | |
("java.lang.RuntimePermission" "accessClassInPackage.sun.security.util") | |
("java.lang.RuntimePermission" "accessClassInPackage.sun.security.x509") | |
("java.lang.RuntimePermission" "createClassLoader") | |
("java.lang.RuntimePermission" "createSecurityManager") | |
("java.lang.RuntimePermission" "fileSystemProvider") | |
("java.lang.RuntimePermission" "getProtectionDomain") | |
("java.lang.RuntimePermission" "loadLibrary.net") | |
("java.lang.RuntimePermission" "loadLibrary.nio") | |
("java.lang.RuntimePermission" "loadLibrary.sunec") | |
("java.lang.RuntimePermission" "modifyThread") | |
("java.lang.RuntimePermission" "modifyThreadGroup") | |
("java.lang.RuntimePermission" "readFileDescriptor") | |
("java.lang.RuntimePermission" "setContextClassLoader") | |
("java.lang.RuntimePermission" "writeFileDescriptor") | |
("java.lang.reflect.ReflectPermission" "suppressAccessChecks") | |
("java.net.NetPermission" "getCookieHandler") | |
("java.net.NetPermission" "getProxySelector") | |
("java.net.NetPermission" "getResponseCache") | |
("java.net.NetPermission" "specifyStreamHandler") | |
("java.net.SocketPermission" "52.34.60.105:443" "connect,resolve") | |
("java.net.SocketPermission" "invariantproperties.com" "resolve") | |
("java.net.SocketPermission" "invariantproperties.com:443" "connect,resolve") | |
("java.net.URLPermission" "https://invariantproperties.com" "GET:") | |
("java.security.SecurityPermission" "getProperty.jdk.certpath.disabledAlgorithms") | |
("java.security.SecurityPermission" "getProperty.jdk.tls.disabledAlgorithms") | |
("java.security.SecurityPermission" "getProperty.keystore.type") | |
("java.security.SecurityPermission" "getProperty.keystore.type.compat") | |
("java.security.SecurityPermission" "getProperty.networkaddress.cache.negative.ttl") | |
("java.security.SecurityPermission" "getProperty.networkaddress.cache.ttl") | |
("java.security.SecurityPermission" "getProperty.securerandom.source") | |
("java.security.SecurityPermission" "getProperty.security.provider.1") | |
("java.security.SecurityPermission" "getProperty.security.provider.10") | |
("java.security.SecurityPermission" "getProperty.security.provider.2") | |
("java.security.SecurityPermission" "getProperty.security.provider.3") | |
("java.security.SecurityPermission" "getProperty.security.provider.4") | |
("java.security.SecurityPermission" "getProperty.security.provider.5") | |
("java.security.SecurityPermission" "getProperty.security.provider.6") | |
("java.security.SecurityPermission" "getProperty.security.provider.7") | |
("java.security.SecurityPermission" "getProperty.security.provider.8") | |
("java.security.SecurityPermission" "getProperty.security.provider.9") | |
("java.security.SecurityPermission" "getProperty.ssl.KeyManagerFactory.algorithm") | |
("java.security.SecurityPermission" "getProperty.ssl.SocketFactory.provider") | |
("java.security.SecurityPermission" "getProperty.ssl.TrustManagerFactory.algorithm") | |
("java.security.SecurityPermission" "putProviderProperty.SUN") | |
("java.security.SecurityPermission" "putProviderProperty.SunEC") | |
("java.security.SecurityPermission" "putProviderProperty.SunJCE") | |
("java.security.SecurityPermission" "putProviderProperty.SunJSSE") | |
("java.security.SecurityPermission" "putProviderProperty.SunRsaSign") | |
("java.util.PropertyPermission" "com.sun.net.ssl.checkRevocation" "read") | |
("java.util.PropertyPermission" "com.sun.net.ssl.enableECC" "read") | |
("java.util.PropertyPermission" "com.sun.net.ssl.requireCloseNotify" "read") | |
("java.util.PropertyPermission" "com.sun.sdp.conf" "read") | |
("java.util.PropertyPermission" "com.sun.security.preserveOldDCEncoding" "read") | |
("java.util.PropertyPermission" "file.encoding" "read") | |
("java.util.PropertyPermission" "http.agent" "read") | |
("java.util.PropertyPermission" "http.auth.digest.validateProxy" "read") | |
("java.util.PropertyPermission" "http.auth.digest.validateServer" "read") | |
("java.util.PropertyPermission" "http.auth.serializeRequests" "read") | |
("java.util.PropertyPermission" "http.keepAlive" "read") | |
("java.util.PropertyPermission" "http.maxConnections" "read") | |
("java.util.PropertyPermission" "http.maxRedirects" "read") | |
("java.util.PropertyPermission" "https.cipherSuites" "read") | |
("java.util.PropertyPermission" "https.protocols" "read") | |
("java.util.PropertyPermission" "https.proxyHost" "read") | |
("java.util.PropertyPermission" "impl.prefix" "read") | |
("java.util.PropertyPermission" "java.home" "read") | |
("java.util.PropertyPermission" "java.io.tmpdir" "read") | |
("java.util.PropertyPermission" "java.net.preferIPv4Stack" "read") | |
("java.util.PropertyPermission" "java.net.preferIPv6Addresses" "read") | |
("java.util.PropertyPermission" "java.net.useSystemProxies" "read") | |
("java.util.PropertyPermission" "java.nio.file.spi.DefaultFileSystemProvider" "read") | |
("java.util.PropertyPermission" "java.protocol.handler.pkgs" "read") | |
("java.util.PropertyPermission" "java.security.egd" "read") | |
("java.util.PropertyPermission" "java.util.logging.SimpleFormatter.format" "read") | |
("java.util.PropertyPermission" "java.util.logging.config.class" "read") | |
("java.util.PropertyPermission" "java.util.logging.config.file" "read") | |
("java.util.PropertyPermission" "java.version" "read") | |
("java.util.PropertyPermission" "javax.net.debug" "read") | |
("java.util.PropertyPermission" "javax.net.ssl.keyStore" "read") | |
("java.util.PropertyPermission" "javax.net.ssl.keyStorePassword" "read") | |
("java.util.PropertyPermission" "javax.net.ssl.keyStoreProvider" "read") | |
("java.util.PropertyPermission" "javax.net.ssl.keyStoreType" "read") | |
("java.util.PropertyPermission" "javax.net.ssl.sessionCacheSize" "read") | |
("java.util.PropertyPermission" "javax.net.ssl.trustStore" "read") | |
("java.util.PropertyPermission" "javax.net.ssl.trustStorePassword" "read") | |
("java.util.PropertyPermission" "javax.net.ssl.trustStoreProvider" "read") | |
("java.util.PropertyPermission" "javax.net.ssl.trustStoreType" "read") | |
("java.util.PropertyPermission" "jdk.internal.lambda.dumpProxyClasses" "read") | |
("java.util.PropertyPermission" "jdk.tls.allowUnsafeServerCertChange" "read") | |
("java.util.PropertyPermission" "jdk.tls.client.protocols" "read") | |
("java.util.PropertyPermission" "jdk.tls.rejectClientInitiatedRenegotiation" "read") | |
("java.util.PropertyPermission" "jdk.tls.trustNameService" "read") | |
("java.util.PropertyPermission" "jsse.SSLEngine.acceptLargeFragments" "read") | |
("java.util.PropertyPermission" "jsse.enableSNIExtension" "read") | |
("java.util.PropertyPermission" "line.separator" "read") | |
("java.util.PropertyPermission" "os.arch" "read") | |
("java.util.PropertyPermission" "os.name" "read") | |
("java.util.PropertyPermission" "proxyHost" "read") | |
("java.util.PropertyPermission" "socksProxyHost" "read") | |
("java.util.PropertyPermission" "sun.jnu.encoding" "read") | |
("java.util.PropertyPermission" "sun.net.client.defaultConnectTimeout" "read") | |
("java.util.PropertyPermission" "sun.net.client.defaultReadTimeout" "read") | |
("java.util.PropertyPermission" "sun.net.http.allowRestrictedHeaders" "read") | |
("java.util.PropertyPermission" "sun.net.http.errorstream.bufferSize" "read") | |
("java.util.PropertyPermission" "sun.net.http.errorstream.enableBuffering" "read") | |
("java.util.PropertyPermission" "sun.net.http.errorstream.timeout" "read") | |
("java.util.PropertyPermission" "sun.net.http.retryPost" "read") | |
("java.util.PropertyPermission" "sun.net.inetaddr.ttl" "read") | |
("java.util.PropertyPermission" "sun.net.spi.nameservice.provider.1" "read") | |
("java.util.PropertyPermission" "sun.nio.fs.chdirAllowed" "read") | |
("java.util.PropertyPermission" "sun.security.rsa.restrictRSAExponent" "read") | |
("java.util.PropertyPermission" "sun.security.ssl.allowLegacyHelloMessages" "read") | |
("java.util.PropertyPermission" "sun.security.ssl.allowUnsafeRenegotiation" "read") | |
("java.util.PropertyPermission" "user.dir" "read") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
("java.io.FilePermission" "/home/bgiles/Documents/src/security-manager/target/classes/com/invariantproperties/sandbox/securityManager/DnsBlockingSecurityManager.class" "read") | |
("java.io.FilePermission" "/home/bgiles/Documents/src/security-manager/target/classes/com/invariantproperties/sandbox/securityManager/Nothing.class" "read") | |
("java.lang.RuntimePermission" "modifyThread") | |
("java.lang.RuntimePermission" "modifyThreadGroup") | |
("java.util.PropertyPermission" "java.class.path" "read") | |
("java.util.PropertyPermission" "java.endorsed.dirs" "read") | |
("java.util.PropertyPermission" "java.ext.dirs" "read") | |
("java.util.PropertyPermission" "java.home" "read") | |
("java.util.PropertyPermission" "java.lang.invoke.MethodHandle.COMPILE_THRESHOLD" "read") | |
("java.util.PropertyPermission" "java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD" "read") | |
("java.util.PropertyPermission" "java.lang.invoke.MethodHandle.DEBUG_NAMES" "read") | |
("java.util.PropertyPermission" "java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD" "read") | |
("java.util.PropertyPermission" "java.lang.invoke.MethodHandle.DUMP_CLASS_FILES" "read") | |
("java.util.PropertyPermission" "java.lang.invoke.MethodHandle.PROFILE_GWT" "read") | |
("java.util.PropertyPermission" "java.lang.invoke.MethodHandle.PROFILE_LEVEL" "read") | |
("java.util.PropertyPermission" "java.lang.invoke.MethodHandle.TRACE_INTERPRETER" "read") | |
("java.util.PropertyPermission" "java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE" "read") | |
("java.util.PropertyPermission" "java.lang.invoke.MethodHandleImpl.MAX_ARITY" "read") | |
("java.util.PropertyPermission" "java.library.path" "read") | |
("java.util.PropertyPermission" "java.system.class.loader" "read") | |
("java.util.PropertyPermission" "java.version" "read") | |
("java.util.PropertyPermission" "java.vm.info" "read") | |
("java.util.PropertyPermission" "java.vm.name" "read") | |
("java.util.PropertyPermission" "java.vm.specification.name" "read") | |
("java.util.PropertyPermission" "java.vm.specification.vendor" "read") | |
("java.util.PropertyPermission" "java.vm.specification.version" "read") | |
("java.util.PropertyPermission" "java.vm.vendor" "read") | |
("java.util.PropertyPermission" "java.vm.version" "read") | |
("java.util.PropertyPermission" "sun.boot.class.path" "read") | |
("java.util.PropertyPermission" "sun.boot.library.path" "read") | |
("java.util.PropertyPermission" "sun.jnu.encoding" "read") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.invariantproperties.sandbox.securityManager; | |
import java.io.File; | |
import java.io.InputStream; | |
import java.io.OutputStream; | |
import java.net.DatagramPacket; | |
import java.net.DatagramSocket; | |
import java.net.InetSocketAddress; | |
import java.net.URL; | |
import java.net.URLConnection; | |
import java.nio.file.Files; | |
import java.nio.file.StandardCopyOption; | |
/** | |
* Simple application that does one simple thing (download a page from a | |
* website) and one malicious thing (exfiltrating sensitive information via a | |
* DNS query). We want to use the SecurityManager to allow the former while | |
* denying the latter. | |
* | |
* @author bgiles | |
*/ | |
public class SimpleApp { | |
/** | |
* This method contains a bit of useful code that we might want to do. | |
* | |
* @throws Exception | |
*/ | |
public static void doSomethingUseful() throws Exception { | |
URL url = new URL("https://invariantproperties.com"); | |
URLConnection conn = url.openConnection(); | |
conn.setDoOutput(true); | |
conn.setDoInput(true); | |
conn.connect(); | |
try (OutputStream os = conn.getOutputStream(); InputStream is = conn.getInputStream()) { | |
os.write("GET /\r\n".getBytes("UTF-8")); | |
os.flush(); | |
File file = File.createTempFile("nothing-", ".html"); | |
Files.copy(is, file.toPath(), StandardCopyOption.REPLACE_EXISTING); | |
} | |
} | |
/** | |
* This method contains a bit of evil code that we do not want to do. | |
* | |
* On the surface we perform a DNS query. This is a common query, esp. if | |
* the loggers perform a reverse lookup of the caller's IP address. | |
* | |
* In fact we're calling our own DNS server and lookup hostnames that look | |
* like | |
* | |
* filename.data.offset.length.example.com | |
* | |
* where the values are encrypted to obscure their nature in case the | |
* security administrator is scanning all packets for sensitive information. | |
* E.g., it might scan for any packet containing NNN-NN-NNNN since that | |
* might contain an unencrypted SSN number or NNNN-NNNN-NNNN-NNNN since that | |
* might contain an uncrypted credit card number. With a bit of care it's | |
* possible to encrypt and encode the payload so it looks like a valid DNS | |
* request. | |
* | |
* The "correct" way to handle this is set up an internal DNS server and | |
* block all DNS traffic going anywhere but this server. That server, alone, | |
* can query white-listed DNS servers on the outside. | |
* | |
* Our security manager sandbox is "defense in depth" and mostly acts as a | |
* monitoring tool since any security exception thrown by it indicates | |
* something is very wrong. | |
* | |
* @throws Exception | |
*/ | |
public static void doSomethingEvil() throws Exception { | |
InetSocketAddress google = new InetSocketAddress("8.8.8.8", 53); | |
try (DatagramSocket dns = new DatagramSocket()) { | |
dns.connect(google); | |
byte[] buffer = new byte[2048]; | |
// populate DNS query | |
// doEvilThing | |
DatagramPacket query = new DatagramPacket(buffer, buffer.length, google); | |
// dns.send(data); | |
DatagramPacket response = new DatagramPacket(buffer, buffer.length); | |
// dns.receive(response); | |
dns.disconnect(); | |
} | |
} | |
/** | |
* Main method. | |
*/ | |
public static void main(String[] args) throws Exception { | |
// important: launch app with | |
// "-Djava.security.manager=com.invariantproperties.LoggingSecurityManager | |
LoggingSecurityManager sm = (LoggingSecurityManager) System.getSecurityManager(); | |
System.out.println("before main..."); | |
sm.listPermissions(System.out); | |
System.out.println(); | |
// do something useful | |
doSomethingUseful(); | |
System.out.println("after something useful..."); | |
sm.listPermissions(System.out); | |
System.out.println(); | |
// do something useful | |
doSomethingEvil(); | |
System.out.println("after something evil..."); | |
sm.listPermissions(System.out); | |
System.out.println() | |
// try it again | |
System.setSecurityManager(new DnsBlockingSecurityManager(sm)); | |
try { | |
System.out.println("trying it again after installing security manager..."); | |
doSomethingEvil(); | |
} catch (SecurityException e) { | |
e.printStackTrace(System.err); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment