Instead of putting the proxy in the String annotation, can it go in an
additional byte array in MarshalledInstance?
This can be used by a trusted lookup service proxy to perform trust
operations on behalf of the client.
During marshalling, if the first Proxy implementing ProxyTrust found in
the stream could be replaced by a token, then serialized into another
array. During unmarshalling, the Proxy would be restricted to the
trusted classes required for proxy verification. Because these are
trusted local classes the proxy doesn't require any annotation to be
unmarshalled.
The proxy could also implement another interface, which after verifying
it's a trusted object and applying constraints, could be requested to
provide an array string of all classes it wishes to unmarshall. Now
since we trust the proxy and have authenticated, we're now preventing a
third party that may have intercepted the stream, from doing harm.
In addition we might ask the proxy for Certificate signers for the
codebase. We could even ask it for the codebase annotation, if we wanted.
At this point the bootstrap proxy is trusted, so we're ready to
unmarshall a smart proxy, if it exists and replace the token that was
inserted during marshalling, with the bootstrap proxy.
Unmarshalling this remote object we could ensure the jar file is signed
by the correct Certificates, and restrict unmarshalling to the list of
classes supplied by the bootstrap proxy.
After unmarshalling we could apply constraints to the smart proxy and
return a fully prepared proxy to the client, resulting in simpler client
code.
Regards,
Peter.
Peter Firmstone wrote:
On 3/05/2013 12:22 AM, Michal Kleczek wrote:
So the problems to solve are:
1. Possible buffer overflow and DoS type of attacks - since we do not
authenticate the stream before deserialization of the first object an
attacker can possibly inject huge objects (of classes available
locally) in the stream (such as LinkedList of arbitrary size).
2. Leverage of vulnerabilities in classes available locally during
object deserialization.
Limiting the list of classes that can be instantiated before doing
codebase verification is a good idea that could possibly solve both
issues. That would be basically providing a small Trusted Computing
Base for security checking of downloaded code.
But that actually means that codebase annotations _should_ be objects
that implement their deserialization in a secure manner so that
attacks from point 1. are not possible. As of today we use
java.lang.String which does not put any constraints on its size.
Objects themselves have no way of limiting the size of the stream
transferred, unless they only read a limited number of bytes and avoid
calling readObject() on the stream, but that's very restrictive and
this would place an unnecessary implementation burden on our trusted
computing base, which would have to be careful not to download
excessive bytes too.
We need to limit the bytes read from the stream until trust is
verified, we could do that by wrapping the InputStream passed to the
MarshalInputStream constructor and counting the bytes read until we
reach our limit, resulting in an IOException and closing the stream,
otherwise the proxy is verified and we set a boolean value to stop
counting prior to reaching the limit.
So we are very close to the solution, but I don't feel that ah-ha
moment yet. I'm off to bed now to sleep on it.
Cheers,
Peter.
To provide backward compatibility we could fall back to old
implementation in case the class is not part of TCB. We would only
allow it if the stream is authenticated beforehand.
Michal
On 2013-05-02 15:35, Peter Firmstone wrote:
On 2/05/2013 9:32 PM, Michal Kleczek wrote:
An attacker can use a serialization attack, without requiring
jini, to create a ClassLoader and start downloading classes out of
band.
Given you never execute untrusted code: how?
I'm glad you asked me this question, because I just stumbled over a
partial solution:
http://www.ibm.com/developerworks/library/se-lookahead/index.html
Ironically I went looking for an example on the web for you, but
this article instead, completely unexpected, this article is very
good because it describes the issues with serialization well. The
article was only written in January this year.
Just possibly we could restrict the classes that
MarshaledInputStream can instantiate to only those required to
perform proxy verification.
Could we limit both the bytes read from the stream and the classes
(required for connection and proxy trust) deserialized from the
stream until proxy verification has been performed?
The challenge is, how can we do this and retain backward
compatibility in marshalled object streams?
If there's an answer to those questions, it's the security grail for
Jini the Sun team was looking for.
Cheers,
Peter.