

Attacking NoSQL and Node.js: Server-Side JavaScript Injection (SSJS) - EwanToo
http://nosql.mypopescu.com/post/14453905385/attacking-nosql-and-node-js-server-side-javascript

======
daeken
This is neat and largely spot on, but I do want to call out one specific thing
that I strongly, strongly disagree with:

> Validate user input used in SSJS commands with regular expressions.

If I had a dollar for every time I saw someone trying and failing to solve
things like SQL injection, XSS, and path injections with regexes, I'd be a
millionaire. It's ridiculously hard to get it right. The best solution is:
don't ever, ever put user input into code. Ever. Build it _based_ on user
input, but don't put user input into the code.

Edit: Just because a lot of people may not be familiar with the pitfalls, here
are a couple things:

\- What character set is your input string, what character set is your regex
engine using, and what character set is the consumer of the input expecting?
An impedance mismatch at any of these points could allow malicious strings to
go right through, even if the regex would normally match it just fine. For
instance, if you're emitting XML and you're using a regex to try and match bad
things in that XML, consider that your regex might miss, say, UTF-16, which
could be totally valid in the XML if you change the charset in the definition
tag.

\- You're building something that generates a file path; you want to restrict
the user from moving up the directory structure and also want to make sure
they're not writing into the 'foo' directory. So you do (in effect): _if path
=~ /\\.\\.\// then bail else return_file(path.replace('foo/', '')) end_ \-- if
a malicious user passes in '../../../../etc/passwd' then it'll get caught by
your filter; if they pass in 'foo/bar.txt' then it'll really read 'bar.txt';
but if they pass in '.foo/./.foo/./.foo/./.foo/./etc/passwd' then it'll read
'../../../../etc/passwd'. If you're modifying things after the regex, be
_very_ careful that you're not compromising the regex.

~~~
CrLf
"using a regex to try and match bad things"

And that's the core failure, not the use of regexes.

Whatever you are using to filter user input, you _always_ filter the good
things in, and not the bad things out.

~~~
ajross
Exactly. For example the common case of filtering "text to be displayed via
the web" is probably _best_ expressed as a (1) a validating conversion to utf8
followed by (2) a regex that translates characters outside the safe range to
XML entities.

------
miles_matthias
Background: I've spent the last four years largely working in the information
security realm, including getting a degree in Information Assurance and
working as a cyber defense intern at Sandia Labs.

<strong>I hate the current state of information security.</strong> My other
degree was in Computer Science and I've switched to be a full-time developer
because the entire security world is full of people and posts like this one.
Listen carefully: It does _absolutely nothing_ to make demos and write posts
that say you can hack things. "I use PHP" "Oh I can hack that!" Everyone can
hack everything. You're missing the point entirely.

Want to help software become more secure? Dive into the software development
process and give real, tangible, code writing advice helping developers learn
what they _should_ do instead of what they shouldn't do.

The advice in this article was "Don't use eval() and use something safer than
JSON.parse()" Wow! Thanks! That's so helpful! How about something like: "When
looking to parse JSON input, use OWASP's ESAPI function here
[http://code.google.com/p/owasp-esapi-
js/wiki/SignedJSONSpeci...](http://code.google.com/p/owasp-esapi-
js/wiki/SignedJSONSpecification)

Or how about some actual tutorials on how to correctly use nosql and sever
side javascript? How about writing an open letter to MongoDB or whoever with
the tutorials and lessons they should be teaching?

I'm sorry for the rant, but I've become enraged over four years of listening
to security experts trying to help security with the most useless tactics. I
understand a lot of them want the glory of showing how they hacked something,
but if you really care about helping the world create more secure software,
you need to understand what will actually help that cause. Boasting your
hacking skills and telling people what to avoid does not help. Be progressive
and proactive - teach people the correct way to do things!

Edit: I just thought of an analogy that might help express what I mean. Ever
seen that show in the Discovery channel (I think it's cancelled now) where the
two ex-robbers go help a family secure their house? First, one of the guys
shows them how exposed they are by breaking in their house and stealing all of
their stuff. Then, the other guy brings in security system tools and shows the
family what they need to be doing in order to protect themselves. Usually the
advice isn't very life changing and the family is happy that they can make
little adjustments in order to be safer. The current state of information
security is exactly like if they had that show without the second guy coming
in and showing how they should protect themselves. There are a ton of security
experts out there that just like to break stuff that get to go hack stuff and
say they're helping people protect themselves when they offer virtually no
advice or education on what to do.

~~~
tptacek
Step back from MongoDB and Node.js and whatnot and look at simple Ruby on
Rails and Django applications. Heck, pan all the way back to J2EE Java web
apps.

Best practices for securing these kinds of applications are well known, well
documented, supported by tutorials and libraries.

How many J2EE applications do you think we work on that survive first contact
with a pentest team?

I don't know what to tell you about the tone of this particular blog post. I
also find the tone of published security research to be grating, especially
over long periods of time, most especially coupled with trade press coverage.

But please do not kid yourself. We are not a few actual tutorials and open
letters (?) away from secure web applications on any stack, let alone the new
ones where developers actually start projects assuming that "NoSQL" does in
fact mean "NoSQLI".

It's best to think of presentations like this as having a very narrow thesis:
"Developers widely assume technology X is free from application security
flaws. In this presentation I demonstrate conclusively that this isn't the
case. The contribution made by this research is the confirmation that
programming mistakes that are similarly pernicious and damaging as SQL
Injection do exist in this technology."

~~~
miles_matthias
Saying that a fundamental different approach is needed to improve software
security is radically different than saying we are "a few tutorials and open
letters from secure web applications." My rant was the former.

~~~
tptacek
I got "tutorials" and "open letters" from your comment.

I fundamentally disagree with the idea that publishing new ways to break
software _isn't_ the best tool we have to improve software security.

But even if I didn't, if you're going to berate someone for publishing an
attack instead of doing something else, the onus is on you to come up with a
plausible alternative.

------
mgkimsal
I'm stereotyping and generalizing a bit, but the crowd I've seen adopting
nosql and node and other "cutting edge tech" _tend_ to be the same people who
mock PHP for being crappy, invoking references to "register_globals"-style
hacks as being one of many reasons why "PHP sucks!"

Is nosql going to (re)teach people that security is something you have to be
vigilant of, regardless of the underlying tech? If so, good.

------
david_a_r_kemp
Simply put: The rules of web development still apply when building sites with
new technologies.

The original paper is based on use of `eval`, which people using NodeJs
wouldn't do (I've not seen one example of it) -especially when V8 has an
efficient `JSON.parse`.

The attack against NoSQL databases is a Sql(JS?) Injection attack - and not
even a sophisticated one. Sure, services like iriscouch open themselves up to
this kind of attack, but the way the paper describes it is pretty much by
design.

~~~
dspillett
People coming from a history of pretty much just client-side programming (or
moving to JS server-side from completely different languages, having worked
with JS client-side) might just use eval because that is what they've done
before (not knowing that JSON.parse exists). The nodejs documents don't
explicitly list JSON as part of its API (because it isn't, it is part of V8's
codebase) so an inexperienced programmer using the node documents as a base
for tinkering might not discover the built-in JSON parser early on so use eval
instead.

Admittedly you should not be using eval() client side either for much the same
reasons you chould not be using it server-side, instead find a decent JSON
library and use it's parse(). Modern browsers include such utility functions
anyway, but you can't rely on them if you need to remain compatible with old-
but-still-common junk like IE6/7/8.

~~~
wwweston
"you should not be using eval() client side either for much the same reasons
you should not be using it server-side"

Can you explain this? I'd think on the server side you'd do it because you
should never trust client input. On the client side, though, presumably you
can trust the input from your own server.

I recognize things can get a bit trickier when you have scripts from untrusted
sources mingling with yours in the same page, but at that point, given the
dynamic nature of JavaScript and the way behavior attached to DOM elements can
be wrapped/changed, I'm not sure eval vs JSON.parse is really your biggest
problem, and I could totally see someone who knew about JSON.parse going with
eval on the client side using that line of reasoning.

~~~
jerf
"I recognize things can get a bit trickier when you have scripts from
untrusted sources mingling with yours in the same page"

Well, that's it exactly. Today's trivial unexploitable vulnerability gets
combined with tomorrow's trivial unexploitable vulnerability and _viola_
arbitrary command execution as the web server user. Or whatever. There's no
vulnerability too trivial to fix, because in reality you can never be sure
that a given vulnerability is unexploitable today, or will remain
unexploitable tomorrow.

------
gizzlon
TL;DR : Don't naively use user input (AKA validate user input)

(well.. duh! :)

~~~
pygorex
Also: don't eval() user-supplied strings.

------
nchuhoai
It would be nice to know whether parts of node.js itself are vulnerable to
those attacks or just badly written user code

~~~
xtian
The paper is just describing common sense stuff: using eval() on user input
and passing user input directly to a database.

~~~
pothibo
With everything node.js provides, I can't understand why someone would use
eval()... Specially with user input.

~~~
jrockway
Of course they wouldn't. "Node.js" and "NoSQL" appear in the title of this
article merely to get people to click the link.

------
MattJ100
A slight feeling of disappointment after reading this post (and the linked
PDF). Partly because the 'attacks' listed are nothing new (we know eval() is
evil), and partly because it's 2011 and people are _still_ writing code like
this.

~~~
jordan0day
"A slight feeling of disappointment... the 'attacks' listed are nothing new
(we know eval() is evil), ... it's 2011 and people are still writing code like
this."

I'm not sure I understand this line of thinking? As you say, people are
_still_ writing code like this -- why shouldn't these problems be called out?

~~~
RobAtticus
I don't think he's disappointed that it's being called out; rather, he's
disappointed that these things still happen.

------
voidr
Arguments like these can be used for pretty much any other technology, this is
not NoSQL nor Node.js specific.

~~~
beaumartinez
Yes, but in very few cases are the server- and client-side languages the same
one.

~~~
daeken
For the purposes of security, I don't think that matters.

~~~
ErikRogneby
It does help explain the temptation of jamming client JSON right into a JSON
object store.

------
ams6110
Goes back to the same thing we've known for years. You must treat all user
input as toxic poison. Do any frameworks take care of this for you
automatically? Because it seems like this is the root of most attacks on web
apps and I'm wondering why we never seem to learn.

