> From: "Peter Firmstone" <peter.firmst...@zeus.net.au> > To: "Remi Forax" <fo...@univ-mlv.fr>, "Alan Bateman" <alan.bate...@oracle.com> > Cc: "jdk-dev" <jdk-...@openjdk.java.net>, "security-dev" > <security-dev@openjdk.java.net> > Sent: Wednesday, July 28, 2021 1:12:32 AM > Subject: Re: How to remove the SecurityManager
> Thanks Remi, > Sand-boxing is a bad idea, we are in agreement, it's not something we do, > personally I'm taking an interest in safer languages, eg Haskell on secure > platforms, eg OpenBSD on Sparc64 *. > Perhaps JEP 411 is simply a reflection on the evolution of languages. Java was > safer than C and C++ so replaced these, something safer again will replace > Java. All mainstream languages have a way to access to raw pointers to be able to call C functions, here is the one in Haskell https://hackage.haskell.org/package/base-4.5.0.0/docs/Foreign-Storable.html > I think people are getting our primary use case, authorization, confused with > sandboxing (not on our use case list). OpenJDK developers provided a Sandbox > example, I just wanted to communicate that I didn't think it was a practical > defense against exploits, nor applicable to our use case: > [ > https://inside.java/2021/04/23/security-and-sandboxing-post-securitymanager/ | > https://inside.java/2021/04/23/security-and-sandboxing-post-securitymanager/ ] > Our process for establishing whether third party libraries are trusted before > we > use them: > 1. Build dependency check using Owasp [ > https://owasp.org/www-project-dependency-check/ | > https://owasp.org/www-project-dependency-check/ ] Reject any dependencies > that > fail, see [ https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/pom.xml | > https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/pom.xml ] line 87 for > an > example of a disabled module due to a vulnerability in a dependency, the > module > will only be re-enabled if the vulnerability is fixed. > 2. Static analysis using SpotBugs, then review identified bugs, review > source > code if available. Reject if security bugs are present, or fix / patch. > 3. Profiling of permission access checks using: [ > > https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/tools/security-policy-debug/src/main/java/org/apache/river/tool/SecurityPolicyWriter.java > | > > https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/tools/security-policy-debug/src/main/java/org/apache/river/tool/SecurityPolicyWriter.java > ] > 4. Reviewing generated policy files, using grep, this example was > generated from > over 2000 tests: [ > > https://github.com/pfirmstone/JGDMS/blob/trunk/qa/harness/policy/defaultsecuresharedvm.policy.new > | > > https://github.com/pfirmstone/JGDMS/blob/trunk/qa/harness/policy/defaultsecuresharedvm.policy.new > ] > 5. Remove any permission from the policy file you don't want to grant to > third > party code, if safe to do so, eg usage statistics reporting. > One of my use cases for SM is for auditing to establish trust, and then using > SM > with POLP policy files generated following the audit, to turn off JVM features > we're not using. Our policy provider is performant and high scaling even with > policy files containing 1000's of lines: [ > https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-platform/src/main/java/org/apache/river/api/security/ConcurrentPolicyFile.java > | > https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-platform/src/main/java/org/apache/river/api/security/ConcurrentPolicyFile.java > ] > Our use of SM for access decisions occurs during and after authentication, but > also defines access roles for trusted parties, it's not possible to replace SM > authorization layer functionality (not to be confused with sandboxes). Our use > case is distributed systems, with trusted services and trusted clients, which > have POJO proxy's, different service proxies are given different > ProtectionDomain identity and these identities are used for authorization > decisions. > In a simple Client - Server application, you only have one user, from the > client > and the thread runs with this permission, but our systems might be performing > a > transaction, with 5 different services, and the transaction service is the > client of these 5 services, which are represented by their proxy > ProtectionDomain's. If one of the authenticated services is not authorized to > participate in the transaction (eg a third party that's not on the contract, > or > maybe the contract expired), then it's not authorized and the transaction will > fail. This all occurs over secure authenticated connections, where both > servers > and clients are authenticated, who's the server and who's the client, well > that > gets a little blurred sometimes. > [ > https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-platform/src/main/java/net/jini/core/transaction/Transaction.java > | > https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-platform/src/main/java/net/jini/core/transaction/Transaction.java > ] > Back in the Jini days, Sun Microsystems, allowed different service proxy's to > be > loaded by the same ClassLoader, if they had the same CodeSource, they had the > same identity if they had the same parent ClassLoader, we don't do that, > ClassLoader's are assigned to a service proxy, based on it's authenticated > identity. > [ > https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-pref-class-loader/src/main/java/net/jini/loader/pref/PreferredProxyCodebaseProvider.java > | > https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-pref-class-loader/src/main/java/net/jini/loader/pref/PreferredProxyCodebaseProvider.java > ] > This system, at its foundations is based on Jini Extensible Remote Invocation > (JERI), we've replaced the serialization layer, to use what we term atomic > serialization and apply constraints during connection establishment over > secure > connections. [ > https://github.com/pfirmstone/JGDMS/tree/trunk/JGDMS/jgdms-platform/src/main/java/net/jini/core/constraint > | > https://github.com/pfirmstone/JGDMS/tree/trunk/JGDMS/jgdms-platform/src/main/java/net/jini/core/constraint > ] > We limit access based on both the service and user identity. We generate our > policy files by profiling (the tool creates a policy file with correct syntax, > ready for immediate use), we recently added replacement of local file paths > with properties for policy property expansion with cross platform > trans-portability. While its possible to use a dynamic proxy without > downloading code, via an atomic serialization connection, it's not generally > advised to do so with unauthenticated users, decisions around dynamic > discovery, whether class loading or downloads are allowed, it's all based on > policy decisions. > The problem with our software is its designed to operate on un-trusted > networks, > and SM infrastructure is involved in authorization decisions during the > authentication process, as well as providing user credentials for secure > connections. > We have no future Java migration path after JEP 411, the decision's been made, > time to move on... > On the bright side, according the JEP 411, we did achieve what OpenJDK dev's > thought to be almost impossible. :) I'm pretty sure using the process I've > documented above, you will identify 99% of accidental vulnerabilities in local > code, and that was good enough for me lol. >> The threat of accidental vulnerabilities in local code is almost impossible >> to >> address with the Security Manager. In your validation process, you have a static part to check the dependencies + SpotBug and a runtime part using a combination of class loader + security manager. For the runtime part, instead of using classloaders, you can use an agent, it will also see all the requests to load a class, it can then do a static analysis of the bytecode to determine if the bytecode only contains kosher method calls and field access, the same way SpotBug does. If you really want to have a mechanism that authorize some method calls or not at runtime, you can change the bytecode to introduce a method call that checks the security policy just before the authorizable method call/field access (you also have to blacklist java.lang.reflect and java.lang.invoke but i supppose you already do this). This approach is better than using a classloader + security manager because - Java allows you to define classes not linked to a classloader since Java 8 (the old API is Unsafe.defineAnonymousClass(), the new one is Lookup.defineHiddenClass()) - you can check any calls not only the ones that the SecurityManager traps. - you can reject calls before loading the class, so earlier than with a SecurityManager, more like the bytecode verifier does. - it's more lightweight in term of memory usage because it does not rely on ClassLoaders (each ClassLoader has its own metaspace, so a lot of CL fragment the memory a lot). To read and transform the bytecode, you can ASM [1], this is one of the library used by SpotBug to read/check the bytecode. (disclaimer: i'm one of the maintainer of that library). It's still not 100% perfect because the agent runs in the same process as the code. (you can go deeper by having the authorization framework in a VM puppeteering a client VM likes jshell does using JVMTI). > * OpenBSD on Sparc (very well supported, Oracle should sell these lol, the > only > drawback is no zfs) is a good idea, no Spectre or Meltdown vulnerabilities. > buffy$ uname -a > OpenBSD buffy.lan 6.7 GENERIC.MP#310 sparc64 > Although this one's a couple of versions behind, time for an upgrade. > Regards, > Peter. regards, Rémi [1] https://asm.ow2.io/ > On 28/07/2021 5:52 am, [ mailto:fo...@univ-mlv.fr | fo...@univ-mlv.fr ] wrote: >> ----- Original Message ----- >>> From: "Alan Bateman" [ mailto:alan.bate...@oracle.com | >>> <alan.bate...@oracle.com> ] To: "Remi Forax" [ mailto:fo...@univ-mlv.fr | >>> <fo...@univ-mlv.fr> ] , "Peter Firmstone" [ >>> mailto:peter.firmst...@zeus.net.au >>> | <peter.firmst...@zeus.net.au> ] Sent: Tuesday, July 27, 2021 6:33:25 PM >>> Subject: Re: How to remove the SecurityManager >>> On 27/07/2021 17:11, Remi Forax wrote: >>>> Peter, this is how you remove the security manager using the jdk 17 (the >>>> SystemMirror class is specific to a JDK version). >>>> Any in-process security measures fail if the API let you to peek and poke >>>> the >>>> memory like Unsafe does. >>> I hope you aren't really suggesting anyone does this :-) >> nope, it's a small example to explain why in-process sandboxing is a bad >> idea. >>> It's dependent >>> on the field layout so can break and crash the VM if it doesn't match. >>> Also it assumes that someone gets theUnsafe before a SM is set. >> yes, it's just an example, you have infinite variations using JNI/JNA/JNR or >> panama and changing some field value. >>> -Alan >> Rémi