The Java Deserialization Bug
fishbowl.pastiche.org
fishbowl.pastiche.org
This is wrong. It is trivial to mitigate this issue and it only takes a couple of lines of code. For a step-by-step guide from 2013 see http://www.ibm.com/developerworks/library/se-lookahead/
1) It only applies to the code you write. Libraries can still use insecure object serialization under the hood i.e. you can't apply this to an built in app server running JMX.
2) It doesn't account for pathological objects, i.e. a billion laughs attack: https://gist.github.com/coekie/a27cc406fc9f3dc7a70d
More details here: https://tersesystems.com/2015/11/08/closing-the-open-door-of...
The related Apache ticket: https://issues.apache.org/jira/browse/COLLECTIONS-580
I suppose -- if you have a Java client for a (probably) EJB-based server; most of the cases where I imagine this sort of setup are with internal-only solutions, though, which mitigates the risk somewhat (but obv. it would still need to be corrected).
I've read about banks in some countries still commonly using Java applets for site access -- that could be a seriously-dangerous attack vector.
That just seems like bad architecture, period. Now if this can be exploited with RMI or something, I wouldn't be too shocked to see some client/server type applications using that as an interface.
are there session cookies that are serialized objects or something?
This was a tech talk intended to broach the subject of dangerous, but standard features of the Java serialization API, providing a demonstration of proof of concept attack vectors.
The truth is that this is not actually a bug. The code works as the design of the OPTIONAL THIRD PARTY library intends. The problem is that this is code that people carelessly deploy, accidentally exposing themselves to attack, failing to understand the full scope and capabilities of their servers and the features they've accidentally included by default.
But then there's data that comes from another team's server calling yours as a service; or from another server internal to your service; or off an internal message bus; or from one's own database.
Each of these has a different degree of trust, and different considerations to weigh.
But, in an application that deserializes objects from an untrusted source, the fact that they happen to be on the class path leads to them being available to use in an undesirable manner.
It would have been nice if ObjectInputStream was abstract and required a subclass that provided a whitelist of classes.
If a serializable object contains a field of type Foo, this implies that all subtypes of Foo can be transmitted, whether they were designed with serialization in mind or not. This is especially bad for commonly used base types such as List or Exception. At the limit, if you have a field of type Object or Any, there's no choice but to use an explicit whitelist.
Contrast with how Go does unmarshaling in its standard library (which works with structs and arrays but not interfaces), and functional languages (which use unions in the form of algebraic data types, not inheritance). These are closed-world type systems where we can generate the whitelist by walking the type tree from the base type.
The algebraic approach, in this context, is similar to a superclass naming its subclasses (rather than a subclass naming its superclasses as java does). I'm not sure, but I suspect this open-world choice is deliberate, allowing extensibility. Java is very attentive to security considerations elsewhere. It also would be a too-dramatic change for mainstream OO programming languages.
A third approach is explicitly closed-world: naming the set of classes permitted for deserialization, as per some other commenters. e.g. JAXB does this by necessity, for binding to XML Schema's algebraic type system.
Or simply having ObjectInputStream execute readResolve/readObject(ObjectInputStream) under a different security context. No need for whitelisting.
Well, yes and no. Java's open-world type system is one of its greatest features. To counteract any security holes this may cause, Java has a very strong security model, where each piece of executable code is associated with a security context based on its origin, and what it is allowed to do is restricted by a security policy based on the code's domain. In this case, however, no foreign code was directly introduced. It was found to be possible to exploit code already found within the application's safe domain (a third-party library).
The Java solution is simple: during deserialization of external data, treat execute custom deserialization code as if it was foreign, and execute it within a foreign security context. It's best if this was done directly in the JDK code, and I assume a patch will adress this.
Is it always? In a language with side-effects (like Java), maybe, but in something like Haskell, surely it would be completely safe?
The logical structure of a file parser is almost indistinguishable from that of a language parser, and most file parsers include what is effectively an interpreter to massage the low-level file instructions into something more meaningful in the loading program's domain model.
A file format is a program that, when evaluated, constructs an in-memory data structure.
The degree to which this is a problem depends on the side effects (if any) of data structure construction, and the set of data structures available to be constructed. And of course how the data structure is used later; if the data structure represents instructions (this is perfectly possible even in pure languages like Haskell) or may behave other than expected with inheritance, more problems ensue.
That's all independent of simple bugs in the parser, such as buffer overflows when trusting lengths and offsets embedded in the file, or infinite loops with naive offset chasing.
of course you could check your desiralised code isn't doing anything unsafe, but that's fairly easy to do in Java too.
Are you saying that Java has something similar to SafeHaskell? Are you saying they are nearly the same? If yes to the last one, I feel that might be untrue.
It's quite possible I just read through your comment too quickly though.