A possible JEP to replace SecurityManager after JEP 411
Peter Firmstone
peter.firmstone at zeus.net.au
Tue Apr 26 07:35:45 UTC 2022
On 25/04/2022 10:53 pm, David Lloyd wrote:
> Nothing in the proposal is intended to solve the issue of tainted
> data; with or without this proposal, this is an unsolved problem.
Well, actually, the statement "this is an unsolved problem" is not entirely true, I think we came very close to solving it. In any case, security is pretty tight:
Perl taint was simple, you parse text data using pattern recognition, the results of pattern matching was considered untainted. Until the data was parsed, it was considered tainted, so it couldn't be used for ODBC etc until it was parsed, it was marked as tainted, so you could delay parsing it if you wanted and Perl would keep track of tainted data.
In JGDMS (evolved from Jini and Apache River) we perform input validation with atomic de-serialization, although we don't mark data as tainted, as it is expected to be validated prior to object instantiation. Every Object in the stream must implement @AtomicSerial, or be a primitive, String or Enum, no circular object graphs are allowed. It is expected that strings will be parsed, or pattern matched, during input validation, unlike Perl taint, it's not something that can be enforced, if Java provided a way to mark Strings as tainted, then we could ensure that any Strings received created directly from stream data are not involved in privileged actions. We could maintain a collection of tainted strings, but then some of them may be identical to strings which aren't tainted, so it wouldn't work as expected, the JVM would need to avoid caching tainted strings. The problem is, to make the String tainted, it would require a permanently unprivileged domain and this isn't easy to do for a final class such as String.
https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-platform/src/main/java/org/apache/river/api/io/AtomicSerial.java
However, in our implementation, de-serialization requires permission, these de-serialization permissions should be granted to ProtectionDomain's based on their (CodeSource || ClassLoader) && Principal's. So the CodeSource should be audited and the Principal trusted (Subject authenticated) before these permissions are granted. The Principal is the source of the data.
https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-platform/src/main/java/org/apache/river/api/io/DeSerializationPermission.java
On the server side, the server usually provides the code that will parse data it receives from the client, however on the client side, the server also provides the code to parse proxy data at the client, so we are heavily dependent on authentication, authorization, encryption privacy and encryption message digests.
Alone, neither the CodeSource nor the Principal, have permission to deserialize, only when both together have permission, only then is de-serialization permitted.
Even though the data source Principal is trusted (and authenticated), the Code must still be audited and trusted to parse the data provided.
A CodeSource may receive permission by its CodeSigner identity, or if the server's authenticated Subject is trusted enough to provide signer certificates, or a message digest of the CodeSource, in which case the client grants permission dynamically.
A single parameter object class provides access to serial data, for all classes in the object inheritance hierarchy.
Every @AtomimcSerial object must check its invariant's, child classes are able to create super class instances, prior to creating an instance of themselves, to allow super classes to check their invariant's. Any object that fails an invariant check, throws an exception prior to calling a super class constructor. Serial parameters have separate namespaces for each class, so a child class cannot see the serial parameters of a superclass, instead it must create an instance of the superclass (which checks it's own invariants) first and then call it's methods and check it's state, the superclass object is not an instance of the child class. Once the child class is satisfied that the superclass instance has been validated, it checks the invariants in its own serial data, prior to creating an object instance of itself (although it is free to check this first, if it is more efficient to do so, eg fail fast).
Collection instances are not serialized, not using Java serialization, but replaced in streams using read only collections backed by arrays. Collection types share the same serial form, such that if Set, List and Map would be equal if compared as objects also have equal serial form. It is the responsibility of @AtoimcSerial classes to check invariant's and make defensive copies of Collections. A utility class, Valid, assists with input validation on collections.
https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-platform/src/main/java/org/apache/river/api/io/Valid.java
Limits are placed on array lengths and stream data, this is a countdown, which must be periodically reset, or an exception will be thrown and control returned to the caller when the limit is reached.
Invocation constraints also provide a way for callers to communicate their intent to underlying communication layers.
https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-platform/src/main/java/net/jini/core/constraint/InvocationConstraints.java
Note that there are extensible layers:
1. Invocation layer
2. Object Identification layer.
3. Serialization layer.
4. Transport layer.
https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-jeri/src/main/java/net/jini/jeri/package.html
These security precautions will no longer provide protection after SM is degraded, hence the need to re-implement an authorization layer.
I had hoped that OpenJDK might assist us by providing hooks we can use to control network access, creation of ClassLoader's or access to properties, or key stores, but it looks as though we have to instrument the Java api's and we are on our own. It also appears due to finalizers, that there will be versions of OpenJDK which we cannot support, eg if SM has been disabled and finalizers are still present, we cannot support this JDK version.
Personally I'd like to see SM fully supported until finalizers can be disabled.
--
Regards,
Peter Firmstone
More information about the security-dev
mailing list