Attacking NoSQL and Node.js: Server-Side JavaScript Injection (SSJS)
nosql.mypopescu.com
nosql.mypopescu.com
> 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.
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.
The way to avoid injection attacks is to make sure you're correctly escaping user input when you use it to compose queries - preferably using a separate abstraction layer rather than calling the escaping function manually.
The most effective tools handle escaping by default, and make you have to work hard to avoid escaping - Django escapes anything output in to a template for example, and the Django ORM handles SQL escaping for you.
<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...
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.
It may be harder to build something good than it is to break things, but it is almost invariably harder to break things than it is to build the average thing.
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."
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.
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.
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.
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.
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.
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.
Is this seriously not well understood? If not, then we should promote more "eval considered harmful" type screeds.
[1] https://www.google.com/search?sourceid=chrome&ie=UTF-8...
I think it needs to not be covered at all for the most part in documentation that might be used by a beginner, in any language not just Javascipt, rather than telling people about it then telling them not to use it.
It gets used because it is sometimes easier than the alternatives. If people don't know about eval() until they have learned enough to be capable of understanding the alternatives and the security implications of eval() then like us they'll do their level best to never use it.
The first rule of application programming is "don't trust user input". eval() requires that the eval'd string be trusted to avoid security holes. The two are mutually exclusive.
In the NodeJS case, this is probably a case of misinformation. If people are teaching the use of unchecked eval, then that's a pretty huge problem. I'd be very interested to see examples in the wild of this happening, though, as it seems like such an obvious mistake that most anyone trying to teach would know to avoid it.
(well.. duh! :)
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?
That does not seem to be the case here, not in the tools, and not in the culture.