EDIT: I'm not familiar enough with clojure; is read-line supposed to be safe?
EDIT: I'm not familiar enough with clojure; is read-line supposed to be safe?
It isn't supposed to be safe, though it can be tempting to treat it as though it's safe.
- It's similar to the YAML reader, in that Java objects can be created. See "deftype, defrecord, and constructor calls" here: http://clojure.org/reader
- On the positive side for the clojure reader, it isn't widely described as a serialization format and people are less inclined to use it for user input. This is a pretty important difference.
- On the negative side, you can not only instantiate objects, but you can execute code. This is what the example in the article does. You can disable that by setting read-eval.
- Also on the negative side, it lacks something quite as secure as YAML's safe_load. You can tell it not to evaluate code, but there isn't yet a way to disable instantiating objects.
As puredanger pointed out, EDN is a better alternative that also comes with clojure. It's designed for data. Clojure's code format is a superset of EDN. http://clojure.github.com/clojure/clojure.edn-api.html
edn limits what is allowed to a safe subset of what read-line will allow, all of the base clojure types and collection types (maps, lists, sets, vectors) are allowed, Java isn't.
Not quite. It reads raw input and tries to build a syntax tree from it. Unfortunately reader macros in clojure allow all sorts of objects to form part of said syntax tree and arbitrary-ish code to run at parse time to instantiate them. But the main job of the reader isn't to evaluate code.
Here I'd say it's a bit different: it's kinda the whole of having read-eval set to true to be able to evaluate code. So when read-eval is set to false and yet rogue code happens to be called there's a serious issue. Basically the issue is that under the hood some Java constructors seems to be called and, if I understand the issue correctly, by knowing how Clojure works you can exploit Clojure / the JVM by crafting precisely what you want to pass to Java constructors (which shouldn't be called in the first place).
Here as I understand it it's not an "eval" exploit per se: it's Java constructors which are passed carefully crafted input.