A suggestion. I think this is a very interesting thread, but I really want
to suggest that we stop. There have been so many changes put into 2.3.0
that need to be reviewed, documented and released. Lets make a concerted
effort to get that done before we make more changes.
Regards
Dennis
On May 2, 2013, at 1048AM, 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.