code as data vs. code injection vulnerability

244 views
Skip to first unread message

Rostislav Svoboda

unread,
May 9, 2012, 8:31:52 AM5/9/12
to clo...@googlegroups.com
I think the topic 'code injection vulnerability' is never out of date
especially if you treat data as a code.
Unfortunately googling for - clojure code injection vulnerability -
returns 'nil'.

Any ideas? Comments? Opinions?

Bost

Baishampayan Ghose

unread,
May 9, 2012, 8:54:08 AM5/9/12
to clo...@googlegroups.com
The problem will only occur if the reader is made to evaluate some
code while reading. Currently this is possible using the #= reader
macro.

For example -

user> (read-string "#=(eval (def x 3))")
;;=> #'user/x

This potentially dangerous feature can be turned off by binding the
*read-eval* var to false before reading the string.

For example -

user> (binding [*read-eval* false] (read-string "#=(eval (def x 3))"))
;;=> ; Evaluation aborted.

Hope this helps.

Regards,
BG

--
Baishampayan Ghose
b.ghose at gmail.com

Tassilo Horn

unread,
May 9, 2012, 9:35:57 AM5/9/12
to clo...@googlegroups.com
I don't think code-as-data contributes to code injection vulnerability,
neither positively nor negatively. Simply don't `eval` code/data from
sources you don't trust.

Bye,
Tassilo
Message has been deleted

Walter Tetzner

unread,
May 9, 2012, 10:02:41 AM5/9/12
to clo...@googlegroups.com
On Wednesday, May 9, 2012 9:35:57 AM UTC-4, Tassilo Horn wrote:

    I don't think code-as-data contributes to code injection vulnerability,
    neither positively nor negatively.  Simply don't `eval` code/data from
    sources you don't trust.


I think it does contribute through the reader. If you are using
Clojure sexps as your data format, and are calling `read' or
`read-string', you have an opening for code injection.

Calling

(binding [*read-eval* false]
  (read-string x))

is clunky, and it's really easy to forget to bind `*read-eval*' to
false.

I feel like `*read-eval*' should default to false, and you should have
to explicitly bind it to true. Either that, or there should be 'safe'
versions of `read' and `read-string' that bind it to false for you.

-Walter

Tassilo Horn

unread,
May 9, 2012, 10:13:33 AM5/9/12
to clo...@googlegroups.com
Walter Tetzner <robot.nin...@gmail.com> writes:

> On Wednesday, May 9, 2012 9:35:57 AM UTC-4, Tassilo Horn wrote:
>
>> I don't think code-as-data contributes to code injection
>> vulnerability, neither positively nor negatively. Simply don't
>> `eval` code/data from sources you don't trust.
>
> I think it does contribute through the reader. If you are using
> Clojure sexps as your data format, and are calling `read' or
> 'read-string', you have an opening for code injection.

Ah, right, I've forgotten about the #=() syntax.

But if you `print` and `read` your data to/from files/databases/whatever
and there's a #=(explode-system) in it, then your system has been
compromised already and you have a problem anyway.

> Calling
>
> (binding [*read-eval* false]
> (read-string x))
>
> is clunky, and it's really easy to forget to bind *read-eval* to
> false.
>
> I feel like *read-eval* should default to false, and you should have
> to explicitly bind it to true.

Yes, probably. And possibly the major use-cases of #=() can be handled
with the new tagged literals in a better and safer way.

Bye,
Tassilo

Stephen Compall

unread,
May 9, 2012, 10:20:37 AM5/9/12
to clo...@googlegroups.com

On May 9, 2012 10:02 AM, "Walter Tetzner" <robot.nin...@gmail.com> wrote:
> I feel like `*read-eval*' should default to false, and you should have
> to explicitly bind it to true.

Yes, but with 'load' binding it to true. You are evalling anyway, and else it would be quite difficult to use just when you need it.

--
Stephen Compall
Greetings from sunny Appleton!

Rostislav Svoboda

unread,
May 9, 2012, 10:53:17 AM5/9/12
to clo...@googlegroups.com
On 9 May 2012 15:35, Tassilo Horn <tas...@member.fsf.org> wrote:
> Simply don't `eval` code/data from sources you don't trust.

In a client-server architecture the thing I (i.e. the server) don't
trust is the client... and I'm not sure if I can ignore him just like
that :)

Bost

Tassilo Horn

unread,
May 9, 2012, 11:31:14 AM5/9/12
to clo...@googlegroups.com
Rostislav Svoboda <rostisla...@gmail.com> writes:

>> Simply don't `eval` code/data from sources you don't trust.
>
> In a client-server architecture the thing I (i.e. the server) don't
> trust is the client... and I'm not sure if I can ignore him just like
> that :)

Not evaluating everything a client sends you doesn't mean ignoring him.
As other's already mentioned, you can read data he sends you, but you
shouldn't eval it, i.e., you should bind *read-eval* to false when
reading data from unknown sources.

Bye,
Tassilo

Craig Brozefsky

unread,
May 9, 2012, 11:32:53 AM5/9/12
to clo...@googlegroups.com
Rostislav Svoboda <rostisla...@gmail.com> writes:

> Many people just copy-paste code snippets to their source files/repl
> withouth really knowing if they are safe or not safe.
>
> IMO it might help to rename the *read-eval* to something like
> *read-eval-ACHTUNG-danger*. For me - as a newbie - it's a better
> proplem indicator than just a simple true/false

I think adding a note to read and friends is sufficient. There could be
other dispatch macros to be considered, not just EvalReader. Having
*read-eval* default to false may also be a good idea.

--
Craig Brozefsky <cr...@red-bean.com>
Premature reification is the root of all evil

Rostislav Svoboda

unread,
May 9, 2012, 11:08:29 AM5/9/12
to clo...@googlegroups.com
On 9 May 2012 15:57, Walter Tetzner <robot.nin...@gmail.com> wrote:
> I feel like *read-eval* should default to false, and you should have to
> explicitly bind it to true. Either that, or there should be 'safe' versions
> of

Many people just copy-paste code snippets to their source files/repl
withouth really knowing if they are safe or not safe.

IMO it might help to rename the *read-eval* to something like
*read-eval-ACHTUNG-danger*. For me - as a newbie - it's a better
proplem indicator than just a simple true/false

Bost

Rostislav Svoboda

unread,
May 9, 2012, 12:01:56 PM5/9/12
to clo...@googlegroups.com
On 9 May 2012 17:31, Tassilo Horn <tas...@member.fsf.org> wrote:
> you should bind *read-eval* to false when reading data from unknown sources.

This is the point! On one hand I need to evaluate data from a client
on the other hand I'd like to filter out things like "rm -rf /", "drop
table users" etc. To me it looks like a contradiction impossible to
circumvent. So I ask if there's anything like "best practices" or even
better something like a concept of access rights or prepared
statements in clojure?. AFAIK there isn't any. So this problem must be
solved on the host platforms (database, operating system etc). To me
this looks much like a wheel-reinventing...

Bost

nicola...@gmail.com

unread,
May 9, 2012, 12:08:38 PM5/9/12
to clo...@googlegroups.com
On Wed, May 9, 2012 at 5:01 PM, Rostislav Svoboda
<rostisla...@gmail.com> wrote:
> On 9 May 2012 17:31, Tassilo Horn <tas...@member.fsf.org> wrote:
>> you should bind *read-eval* to false when reading data from unknown sources.
>
> This is the point! On one hand I need to evaluate data from a client
> on the other hand I'd like to filter out things like "rm -rf /", "drop
> table users" etc.

The best practice is to not evaluate data from your client but to read
it, and process it.
It is a hard problem to decide if a given piece of code in any
language can be safely evaluated or not.
If you really need to evaluate program from hostile clients, design a
small language allowing only safe
programs and write a translater into clojure then eval the result.

Michael Gardner

unread,
May 9, 2012, 12:15:21 PM5/9/12
to clo...@googlegroups.com
On May 9, 2012, at 11:01 AM, Rostislav Svoboda wrote:

> This is the point! On one hand I need to evaluate data from a client
> on the other hand I'd like to filter out things like "rm -rf /", "drop
> table users" etc. To me it looks like a contradiction impossible to
> circumvent. So I ask if there's anything like "best practices" or even
> better something like a concept of access rights or prepared
> statements in clojure?. AFAIK there isn't any. So this problem must be
> solved on the host platforms (database, operating system etc). To me
> this looks much like a wheel-reinventing...

Or you can just use something like XML or a custom language for data transfer, which also avoids trying your clients to Clojure. I've never understood why anyone would use prn/read for data transfer, other than extreme laziness.

Stuart Halloway

unread,
May 9, 2012, 5:31:03 PM5/9/12
to clo...@googlegroups.com
(1) Using Clojure as a print/read format does not tie your clients to Clojure. Readers exist in many languages, and are easy to implement. 

(2) XML, despite its baroqueness, is extensible. So is Clojure data. This is a big advantage, and many approaches lack it.

Cheers,
Stu


Stuart Halloway
Clojure/core
http://clojure.com

Lee Spector

unread,
May 9, 2012, 7:38:14 PM5/9/12
to clo...@googlegroups.com

On May 9, 2012, at 12:15 PM, Michael Gardner wrote:

> I've never understood why anyone would use prn/read for data transfer, other than extreme laziness.

But extreme laziness is an excellent reason!

Larry Wall called laziness "the first great virtue of a programmer."

-Lee

Softaddicts

unread,
May 9, 2012, 7:54:54 PM5/9/12
to clo...@googlegroups.com

>
> On May 9, 2012, at 12:15 PM, Michael Gardner wrote:
>
> > I've never understood why anyone would use prn/read for data transfer, other than extreme laziness.
>

When I encounter the ancestor of XML in the mid 80s, SGML, it was used as a
typesetting tool for laser printers, just before the era of WYSIWYG begun.

I never understood why these days we need to typeset data before
sending it to another piece of code, does the software really care about the look ?

We used to have things called specs to decipher messages
and bandwidth was at premium. XML is like ordering a hardcopy book from Amazon
and getting the whole apparatus to print it at the same time...

Luc


--
Softaddicts<lprefo...@softaddicts.ca> sent by ibisMail!
Reply all
Reply to author
Forward
0 new messages