-
Notifications
You must be signed in to change notification settings - Fork 14
Add warning against running untrusted templates #17
Comments
Good point! I wonder if other templating autoescaping escapes |
Auto-escaping works on the variables you feed into the template, not in the template itself. (and correctly fixes the problem: http://jsfiddle.net/vjeux/3rzsn4sy/ ). What I'm trying to point here is that it's not safe to have the user define the template itself. |
Oh, duh, right. I misinterpreted. Yeah, of course by default it will output HTML. I will add a warning to the docs. |
I think the fact that rendering a template can execute arbitrary javascript code on the server is even more unexpected nunjucks.renderString('{{a.constructor.__proto__.constructor("alert()")()}}'); |
We parse a grammar similar to JS, and output the corresponding JS to the AST, so yes, those holes are exposed. Accessing native methods is an easy way to get a lot for free, so users can just do {{ arr.length }} and stuff. You're right though; we should blacklist a few properties that allow you to access this so that this safety is on by default. I know other engines have a "sandboxed" mode which we could also support. Is there anything other than Regardless, I will add a warning that we don't guarantee a full sandboxed mode yet. |
Blacklisting properties is very dangerous. If you ever attempt to have a sandboxed mode, I would highly recommend you talk to someone with a web security background. Cure53 audited most of the template engines out there. https://code.google.com/p/mustache-security/ They also privately audited React and had a lot of good suggestions to improve it's security edge cases :) |
Yeah, blackboxing is just a false sense of security. Nunjucks does not really provide a solution for user-defined templates that should not be able to run arbitrary JS. Some of the current products that use nunjucks are CMS-es where this doesn't matter, because you are using it to customize your own site and you could freely run JS in just a Handlebars is a better solution for a completely safe user-defined template. I will add notes about this in the docs somewhere. |
I added a warning in the updated docs (published soon, thanks!) |
For those reading this, there are two bits of info that may be helpful:
|
Hi @vjeux, what exactly is this supposed to do, and how does it work? nunjucks.renderString('{{a.constructor.__proto__.constructor("alert()")()}}'); I checked out the JSFiddle and it doesn't do anything. I'm guessing it's because I'm on a newer version of Chrome? |
The variable |
Thanks @vjeux! |
In JavaScript, you can define a function statically: function() { alert() } or dynamically from a string Function("alert()") I'm using Once you have a function created like this, you can call it Function("alert()")() in order to execute it. So now, the game is all about figuring out a way to access the If you have access to any function, you can get (function() {}).constructor === Function // true nunjucks won't let you define anonymous functions like that either. If it would, we could just have done What we can do is to create a new object and ask for its constructor, which is a function. We don't really care what that function does, the important thing is that it's a function. ({}).constructor // function from there, we can access ({}).constructor.constructor === Function // true At this point we won, now we just need to assemble everything back together ({}).constructor.constructor("alert()")() and we're done. In the example above I added a |
Thanks so much @vjeux! I'm re-writing my template engine, Squirrelly, and wondering if I should implement some of these protections like preventing the user from accessing global variables, etc. Currently, I'm thinking that I'll just have Squirrelly as a tool to output untrusted JavaScript, and a tool which shouldn't be used with untrusted data or templates. In your opinion, does this sound like a bad idea? |
You should likely treat the data that you pass as untrusted: if someone sets his username as For templates, if they are part of a build system and only requiring sources checked in the repo. Then this is trusted and fine. But for a lot of template systems, it's just a function call with a string. So it's --very easy-- to have someone that work in your codebase pass a dynamic string that is built with user-provided information. Then you're screwed if you don't have a proper sandbox, which all the templating engines that were written pre-react that I know about didn't have. If you go that route, be aware that doing proper protection is --very hard--. You should look at projects like https://developers.google.com/caja/ instead of trying to fix it yourself. |
Can't you just use something like DOMPurify as a wrapper to fix this issue? |
I talked to people that are under the impression that it's safe to feed user-defined templates to nunjucks. However it is not. It may be good to add a warning about this.
Proof of concept to run arbitrary code on viewers: http://jsfiddle.net/vjeux/q55ads7r/
Proof of concept to run arbitrary code on the execution environment: http://jsfiddle.net/vjeux/2kcjjgt2/
The text was updated successfully, but these errors were encountered: