peter.firmstone at zeus.net.au
Thu Feb 11 08:47:26 UTC 2016
The use case here is:
Do we trust the code to deserialize unverified data from an untrusted
For example, an attacker might look for the following:
1. Deserialization into privileged context
2. Deserialization with a class that catches and ignores IOException.
3. A hash collission that will cause equals to be invoked on a proxy
and invocation handler.
History has shown us that no permission was required to perform these
In this case, I'm not concerned who or which object might obtain a
reference to some object that's serializable, because anyone can do so
using a crafted stream reference.
An attacker can obtain a reference to any object in the stream using a
Objects that shouldn't escape a permission check in a constructor or
being returned from some method call containing a permission check,
shouldn't be serializable.
What I'm concerned about is, do we trust all classes belonging to this
object's heirarchy to read unverified data from the stream and verify it
before creating an object?
Ideally the stream should be deserialized into a context that has no
permission, but currently we have no way of restricting the attack
surface to include only those classes necessary to perform some function.
We could use the traditional stack context of the calling thread, as you
It is true, an object that contains a field that didn't have
deserialization permission, would itself become unserializable.
> On 02/08/2016 10:19 PM, Peter Firmstone wrote:
> >/ Why not, just prior to instantiating an object just prior to deserializing, add each class' ProtectionDomain in the objects hierarchy to an AccessControlContext and pass this to the SecurityManager's two argument checkPermission call?
> />/ This permission could never be granted to a principal, it is only ever a code trust concern. This would allow an administrator to minimise the attack surface of Serializable classes.
> I think rather than using the ProtectionDomain of the objects in the
> serialization stream, would it not make more sense to capture and use
> (exclusively) the access control context of the entity which is
> constructing the stream? The reason I say this is that it's very
> possible for a less-privileged object to have references to
> more-privileged objects and vice-versa; also, in some cases you're
> predicating the success of deserialization upon the order in which
> objects are deserialized.
> For example, if I have a four-object graph of A, B, C, and D, in a
> diamond like this:
> If B's class does not have privileges to construct D, deserialization
> will fail, even if C does. On the other hand, if B has permission to
> construct D, but C doesn't, C can escape its restriction by relying on B
> to have already deserialized the object.
> But by using one permission set - the captured context of the creator of
> the stream, or perhaps the captured context of the "root" readObject()
> call, you cannot change the authorization outcome of the deserialization
> just by fiddling with the bits. A graph in this case is either valid or
> - DML
More information about the core-libs-dev