DeserializationPermission Proposal

Peter Firmstone peter.firmstone at zeus.net.au
Thu Feb 11 09:52:51 UTC 2016


An example might be more useful.

Traditionally, when the first non serializable superclass zero argument 
constructor is called, the domains of the subclasses aren't present on 
the call stack.  Any security checks performed in the constructor of the 
superclass will not include the subclasses domains.

In the proposed case, prior to construction, all domains in the class 
heirarchy of the to be deserialized object via the local 
ObjectStreamClass, are added to an AccessControlContext, which is then 
passed to the SecurityManager two argument permission check.

Now an attacker will not be able to construct this object unless all 
domains have DeserializationPermission.

If we use the stack context, it won't contain the yet to be deserialized 
classes.

Regards,

Peter.

On 11/02/2016 6:47 PM, Peter Firmstone wrote:
> The use case here is:
>
> Do we trust the code to deserialize unverified data from an untrusted 
> source?
>
> 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 
> actions.
>
> 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 
> stream reference.
>
> 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 suggest.
>
> It is true, an object that contains a field that didn't have 
> deserialization permission, would itself become unserializable.
>
> Regards,
>
> Peter.
>
>
>> 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:
>>
>> A->B
>> A->C
>> B->D
>> C->D
>>
>> 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
>> not.
>>
>> -- 
>> - DML




More information about the core-libs-dev mailing list