Explicit Serialization API and Security
Peter Firmstone
peter.firmstone at zeus.net.au
Fri Jan 23 07:10:51 UTC 2015
And that is the point of this discussion, to determine how to do just that.
But considering it's such a difficult problem, we haven't figured out how to yet.
Peter.
----- Original message -----
>
> Message: 2
> Date: Wed, 21 Jan 2015 15:43:13 -0600
> From: "David M. Lloyd" <david.lloyd at redhat.com>
>
> At some point, the responsibility *must* fall on the author of the
> serializable class in question to avoid constructs which are exploitable
> - like finalizers, and classes that can have side-effects before
> validation can be completed.
>
> On 01/21/2015 02:26 PM, Peter Firmstone wrote:
> > Don't forget that "null" may also be an invalid state.
> >
> > What I have learnt so far:
> >
> > 1. An attacker can craft a stream to obtain a reference to any object
> > created during deserialization, using finalizers or circular links
> > (there may be yet other undiscovered methods).
> > 2. An attacker can craft a stream that deliberately doesn't satisfy
> > invariants, in order to use an object to perform a function that
> > wasn't intended by its developer.
> > 3. Objects that interact with the stream directly using readObject et
> > al, are often prone to DOS. Example, many objects read a length
> > integer from the stream when creating an array or collection,
> > without first validating it.
> > 4. Objects that interact directly with the stream become an implicit
> > part of the stream protocol.
> > 5. Once you allow an object to be created, it's too late to
> > invalidate invariants, unless the class is final and invariants
> > are checked in every method call.
> > 6. We need to be able to restrict classes used for deserialization to
> > those we trust to check invariants properly (but we haven't
> > provided a way for them to avoid object construction yet).
> > 7. A static validator method can ONLY be used to check field
> > invariants, not other objects and primitives that are read
> > directly from the stream by an arbitrary Object during the process
> > of deserialization.
> > 8. The jvm can be modified to delay finalizer registration for
> > deserialization.
> > 9. Circular links can be disallowed.
> >
> > Ultimately however, all proposed changes add complexity, but when an
> > object has been created with invalid invariants, an attacker will find
> > a way.
> >
> > Thank you all for your time, this has been a very good discussion.
> >
> > Regards,
> >
> > Peter.
> >
> > On 22/01/2015 2:27 AM, Chris Hegarty wrote:
> > > On 20/01/15 20:22, Peter Levart wrote:
> > > > Hi Chris and Peter,
> > > >
> > > > It just occurred to me that the following scheme would provide
> > > > failure atomicity for the whole Object regardless of whether
> > > > readObject methods are used or not for various classes in
> > > > hierarchy:
> > > >
> > > >
> > > > - allocate uninitialized instance
> > > > - call default accessible constructor of the most specific
> > > > non-Serializable class
> > > > - deserialize (by calling readObject methods where provided) the
> > > > fields of all classes in hierarchy like normally
> > > > (up to this point, nothing is changed from what we have now)
> > > > - if deserialization fails anywhere, undo everything by setting
> > > > all the fields in the Serializable part of the hierarchy to
> > > > default values (null for references, 0 for primitives), abandon
> > > > the object and propagate failure.
> > >
> > > I think this is a good idea, and I can prototype something to this
> > > affect.
> > >
> > > -Chris.
> > >
> > >
> > > > While deserializing, the object is in inconsistent state. If
> > > > deserialization fails, this state is rolled-back to uninitialized
> > > > state. finalize() can still get to the instance, but it will be
> > > > uninitialized.
> > > >
> > > >
> > > > Peter
> > > >
> > > > On 01/14/2015 01:58 PM, Peter Firmstone wrote:
> > > > >
> > > > > Hi Chris,
> > > > >
> > > > > Sorry, no.
> > > > >
> > > > > Currently when an ObjectStreamClass is read in from the stream,
> > > > > the framework searches for the first zero arg constructor of a
> > > > > non serializable class and creates and instance of the class
> > > > > read and resolved from the stream, however it does so using a
> > > > > super class constructor.
> > > > >
> > > > > Then from the super class down, fields are read in and set in
> > > > > order for each class in the object's inheritance hierarchy.
> > > > >
> > > > > The alternative I propose, doesn't create the instance, instead
> > > > > it reads the fields from the stream, one by one and without
> > > > > instantiating them, if they are newly read objects, stores them
> > > > > temporarily into byte [] arrays in a Map with reference handle
> > > > > keys, otherwise it just holds the reference handle.
> > > > >
> > > > > What it does next is wrap this information into a caller
> > > > > sensitive api, GetFields or ReadSerial instance, that is passed
> > > > > as a constructor parameter to the child class serial constructor.
> > > > >
> > > > > The child class checks invariants and reads each field it needs
> > > > > using a static method prior to calling a superclass constructor,
> > > > > each class in the inheritance hierarchy for the object then
> > > > > checks its invariants until it gets to the first non
> > > > > serializable superclass.
> > > > >
> > > > > The benefit of this order is that each class is present in the
> > > > > thread security context, so protection domain security and
> > > > > invariants are enforced before instantiating an object.
> > > > >
> > > > > Hope this helps illuminate it a little better, regards,
> > > > >
> > > > > Peter.
> > > > >
> > > > > ----- Original message -----
> > > > > > Peter F,
> > > > > >
> > > > > > I am still struggling with the basic concept of you proposal.
> > > > > > Let me
> > > > > see
> > > > > > if I understand it correctly. Does the following describe a
> > > > > > similar scenario as you envisage:
> > > > > >
> > > > > > 1) For each Serializable type, T, in the deserialized types
> > > > > > hierarchy, starting with the top most ( closest to
> > > > > j.l.Object ),
> > > > > >
> > > > > > 1a) Read T's fields from the stream, fields
> > > > > >
> > > > > > 1b) validate(t, fields) // t will be null first time
> > > > > >
> > > > > > 1c) allocate a new instance of T, and assign to t
> > > > > >
> > > > > > 1d) set fields in t
> > > > > >
> > > > > > 2) Return t;
> > > > > >
> > > > > > So for each level in the hierarchy, an instance of a type is
> > > > > > created only after its invariants have been checked. This
> > > > > > instance is then passed to the next level so it can
> > > > > > participate in that levels
> > > > > invariants
> > > > > > validation.
> > > > > >
> > > > > > If this scenario is along the same lines as yours, then I just
> > > > > > don't
> > > > > see
> > > > > > how 1c above will always be possible.
> > > > > >
> > > > > > If we could somehow make the object caller sensitive until
> > > > > > after deserialization completes, then could avoid having to
> > > > > > try to allocate multiple instance down the hierarchy.
> > > > > >
> > > > > > -Chris.
> > > > > >
> > > > > > On 13/01/15 10:24, Peter Firmstone wrote:
> > > > > > > Could we use a static validator method and generate bytecode
> > > > > > > for constructors dynamically?
> > > > > > >
> > > > > > > The developer can optionally implement the constructors.
> > > > > > >
> > > > > > > static GetField invariantCheck(GetField f);
> > > > > > >
> > > > > > > Create a caller sensitive GetField implementation and add a
> > > > > > > two new methods to GetField:
> > > > > > >
> > > > > > > abstract Object createSuper(); // to access superclass
> > > > > > > objectmethods for inavariant checking.
> > > > > > >
> > > > > > > abstract Class getType(String name);
> > > > > > >
> > > > > > > Set fields from within constructors.
> > > > > > >
> > > > > > > The generated constructors are straight forward:
> > > > > > >
> > > > > > > 1. Call static method.
> > > > > > > 2. Call super class constructor with result from static
> > > > > > > method. 3. Set final fields
> > > > > > > 4. How to set transient fields, implement a private method
> > > > > > > called
> > > > > from
> > > > > > > within the constructor?
> > > > > > >
> > > > > > > Require a permission to extend GetField?
> > > > > > >
> > > > >
> > > >
> >
>
> --
> - DML
>
>
> --------------
More information about the core-libs-dev
mailing list