This got me thinking about how other languages tend to lend themselves to certain vulnerabilties. We're all aware of buffer overflow exploits; these are due almost entirely to the fact that C/C++ force you to waste time managing memory. Such things are virtually non-existent in languages like Lisp or even Java.
So what kinds of vulnerabilities does Lisp usage tend to open you up to? The only thing I can think of are the potential hazards involved in using
read
. As we had to keep in mind when developing Paragent, you absolutely must set *read-eval*
to nil wherever you use read
. Otherwise, you are at great risk from the #. macro, which will essentially allow an attacker to (easily) run any code they want on your machine. Happily, it's easy enough to avoid once you're aware of it.Beyond that, I'm at a loss. Can anybody else think of some security issues that are particular to Common Lisp?
9 comments:
There's the risk of DOS by KEYWORD package overgrowth: if you intern for instance HTTP header names as keywords you expose yourself to an attack where you receive headers with extra-long random names which could cause large memory consumption.
Then there's the risk of being overly aggressive with SPEED optimizations, in which case buffer overflows could very well happen in CL too.
Cruel Fate has lately had me doing a great deal of work in ColdFusion.
My day job keeps me in the ASP.NET land and so far it's proven to be a (mostly) pleasant framework for building web apps. I have a legacy app that I inherited that's written in ColdFusion and I quickly learned that I absolutely can't stand that environment. I always thought it was just my limited knowledge of the language and the methodology but your use of the words "Cruel Fate" makes me wonder....
Here's are two candidates:
a) CLOS behavior is underspecified when you store a value of type X into a slot of type Y. SBCL, at least, will signal a condition when you do this with (debug 3), but not with (debug 0). So if your code relies on those conditions to validate user input, you immediately become vulnerable to malformed input.
Generally, the combination of behavior unspecified by the spec, and made friendly by an implementation (but only at certain debug levels) is a minefield.
b) God help you if you take a string from the user, and then call (format value) to show it back to them. ~// is terrifying.
There's also package "pollutrion" problems. If you keep reading symbols in a package, there's a risk of the package symbol structure growing unbounded. One work-around is doing each "reading pass" in a specially-constructed package, IMPORTing the symbols you care about from a specific package and then use DELETE-PACKAGE to make it go away.
Could you explain a bit more the Lisp part for users unfamiliar with Lisp? For someone who doesn't know Lisp it looks very strange. The read should just read data and that's it.
@Christian
Lisp's read is not like fread or iostream::read or any other file based read. It's reads some Lisp source code, compiles it and gives you the result.
I see. So the read name is a bit unfortunate, just like Python's input, but on the other hand the documentation is clear about what it does and a user shouldn't use a function without reading its documentation.
You were looking fine until you shouted your ignorance through this sentence: these are due almost entirely to the fact that C/C++ force you to waste time managing memory
Great blog you got here. It would be great to read more concerning that topic. Thanx for posting that data.
Sexy Lady
English escort
Post a Comment