Break Google
mahdiyusuf.com
mahdiyusuf.com
http://code.google.com/p/google-ctemplate/
It makes sense that the ${ could cause problems.
If you did click and skim the page at 1000000000 words/sec, those `$` over there are for USD, and not part of templating system.
Minimal reproduction:
Mustache.to_html('{{b}}', {b: '{{c}x}' }) -> '{{c}x}'
Mustache.to_html('{{#a}}{{b}}{{/a}}', {a: [{b: '{{c}x}' }]}) -> '{{c}x}'
Mustache.to_html('{{b}}', {b: '{{c}}' }) -> '{{c}}'
Mustache.to_html('{{#a}}{{b}}{{/a}}', {a: [{b: '{{c}}' }]}) -> '' (wrong)The fact that Google brings back an empty result set to me indicates the problem is a bit deeper...
The base reward for qualifying bugs is $500. If the rewards panel finds a particular bug to be severe or unusually clever, rewards of up to $3,133.7 may be issued.
http://googleonlinesecurity.blogspot.com/2010/11/rewarding-w...
The crazy lucrative bugs you may have heard of tend to be drive-by remote code execution in popular clientsides (like IE or Flash), and the stories about valuations tend to be apocryphal.
Either google is very confident that they don't have serious bugs or they are setting themselves up for a problem. Imagine the value of finding a serious bug in adsense or adwords.
The bug doesn't exist on https://encrypted.google.com/
Guys, (and I don't mean Google, I mean all of us), don't fix injection by plugging injection bugs; put together some framework that actually avoids all of these problems (or at least doesn't let you add bugs).
As an example of a difficult case, consider the following pseudocode snippet:
...
if request['raw']:
print("Content-Type:text/plain; charset=utf-8\r\n\r\n")
print(doc)
else:
print("Content-Type:text/html; charset=utf-8\r\n\r\n")
print(html_sanitize(doc))
...
In one branch, doc must be HTML-sanitized; in the other branch, it must not.What the GP is saying (and I agree with) is that generate_html() should use a library which understands HTML structure and only allows content to be generated using a strict API (no doc+="<foo>bar</foo>" garbage).
Such a discipline greatly reduces the chance of injections, to the point where you have to actively write code to create injection points. And it's simple to follow: any time you write HTML, use the library.
Taint analysis sounds nice in theory, but you can get the same effect by writing code modularly (i.e. only one small module can actually access the raw output stream) and using libraries to create structured data.
I do not currently write my blog posts in a templating language (any more than anyone else does), though Hamlet [1] has me sort of tempted as it is so close to what I write anyhow.
Then, the framework could map different kinds of requests (e.g: raw content vs. html content) to different types.
Then, the only way to convert between the types are functions that do proper escaping.
Due to django's "we want the templating system be general, to be usable for stuff other than html", it can't provide support for such 'guarantee that the output is well formed / valid / has no injection attack entry points' features.
Everything is escaped by default, and you have to explicitly request for your content to be unescaped.
How do you handle user-submitted image tags? Do you allow rich formatting, and if so, how do you sanitize it? (see http://www.codinghorror.com/blog/2008/08/protecting-your-coo...)
I think that Django uses sha for password hashes. They should use bcrypt, right? Did you turn on XSRF protection (which I think is off by default)? Are cookies secure?
Web security is not as simple as 's.replace("<","<")' (escaping by default).
How do you generate slugs? Could someone put something nasty in a pathname or URL?
Django is not secure. You can secure it, with minimal effort, if you keep things radically simple. But you do need to know what can go wrong, so you don't introduce any "features" that are actually "gaping security holes".
Even if you do everything right, it doesn't mean that Django is magically secure no matter what people use if for (obvious, yes, but this is HN and sometimes failing to point out the obvious can get you downvoted). That's why people are objecting.
Like any framework, there will always be room to improve security, but it does do very well out of the box. At least it makes you work to expose anything obvious.
Django uses sha for password hashes because until recently there hasn't been a better library to ship with natively across all the platforms that Django supports. If you know you'll only be working on *nix, django-bcrypt can enhance the default password hashing behavior. As other commenters have noted, they're moving to PBKDF2 in the near future as a better included hashing library.
CSRF is on by default. If you need secure cookies and HSTS headers, there's a package that provides them called django-secure, which last I heard is being rolled into Django proper in the near future.
Django prevents path traversal and anything else you can imagine that might be nasty in a URL. The auto slug generation included.
So how exactly is Django not scure again? Where are the "gaping security holes"? Or do you have no idea what you're talking about.
I'll refer to something I wrote last time I had this argument: http://pavpanchekha.com/programming/injection.html.
I disagree with the articles premise that injection is always a display issue. In the [Yesod web framework](http://www.yesodweb.com) which uses Hamlet, we sanitize, not strip html by default before it is ever put in the database. The more you can make injection not a display issue, the better- you just have to know your options.
Based on the fact that the suggestions in your blog article could easily support someone forgetting the "|escape" on a variable, I would accuse your methodology of only solving the "90% problem".
Edit: I guess it would be more helpful to explain why for those not familiar with XSS. If all it takes it a specially crafted URL to your site to exploit it, your site is toast. The security model of the web assumes that people can open even the shadiest of links without negative consequences. I could have obscured the URL with a shortener and named the link "Cutest cat pic ever!" I could have hosted a page on a totally separate domain and put the crafted URL in a hidden iframe. All I have to do is send document.cookie over to my server and now I control your account.
${KEYWORD}${
If you can figure out what "KEYWORD" is for a given template tag as well. I tried links and a few others, but none that I can identify: it does still reproduce the bug though.
https://encrypted.google.com/#q=${
looks fine, but
http://www.google.com/search?sourceid=chrome&ie=UTF-8...{
doesn't.
Loading http://www.google.com/search?q=${ does what you see, but entering ${ in to the search box and pressing enter does what everyone else sees.
edit: compare your clean human generated address bar to the other screenshot's messy software generated one.
${
However, I tried the literal
'${'
Which also breaks it. In fact, it looks like anything that has ${ in it will break it, anywhere at all in the search string.
Also, if you close the parentheses, e.g. ${}, it fixes it. This works with any number of leading ${, e.g. ${${${${${}
not sure if that was intended or not.
http://mikewest.org/2007/06/escaping-curly-braces-in-xslt-at...
I s'pose attributes don't enter into it, but still, I wonder if the XSLT pass (if any) has anything to do with this?
Making it an actual hyperlink would've been a bit shorter.
Still, this obviously doesn't look good. Above anything else google has excelled on being simple and reliable. All this javascript goodness added recently might be a step in the wrong direction. If stuff like this starts to happen every now and then, google's reputation might be at stake.
Imagine how much easier life would be if in HTML we only had to filter for § instead of escape every <, > and ".
http://www.proweb.co.uk/~matt for instance
Reading it now as a treatise from my younger self, though I didn't write it, I realise that spirit is lost. For a while it was "our" place but now we have to return to the underground.