Handlebars JS is processing HTML as String [duplicate] - javascript

I use handlebars, and if an escaped character such as ' is processed it is rendered on screen as '.
I know wrapping the variable in a triple-stash will prevent this.
I processed the following string within a triple-stash as a quick test and it seemed fine "<p>hello<p>wouldn't wouldn't" This rendered to screen exactly how I wanted it to.
My question is, is it safe to simply wrap all variables in triple-stash? or will this have some unforeseen consequences I haven't considered?
Thanks

By default all double-stashed {{var}} embeds in Handlebars will be HTML-escaped. It's performed for security reasons to avoid DOM XSS vulnerabilities. Because your variable may contain any data including user-data or any kind of untrusted data.
In some cases you will need to embed your data as-is, without escaping. There is where tripple-stash {{{var}}} used. But every time doing this, you need to think what may be in your data and can you trust it?
Read more about HTML Escaping on Handlebars site.

Related

JavaScript / Lit-element safe way to parse HTML

I am getting some html from my server that I want to put into my page. However I want it to be sanitized (just in case).
However I am not quite sure how to do this.
So far I've tried:
<div .innerHTML="${body}"></div>
Since that should parse it as HTML but I am not 100% sure that this is the best way.
I have also looked at online sanitizers but haven't been able to find any that match my project (Lit-element web component).
Is there a better way to parse HTML and if so how?
Take a look at the DOMParser interface API
document.getElementById('my-target').append(new DOMParser().parseFromString(data, 'text/html').body.children);
It's not clear whether you want to render the html as html or as text.
I seem to remember that lit-html does some things behind the scenes to produce secure templates but surprisingly I cannot find official content to back up that statement. Others have asked about this before.
In that GitHub issue we can see that Mike Samuel mentions that what you're doing is not secure.You can trust Mike Samuel: he's worked in the security field at Google and I had the privilege to listen to one of his talks on the topic two years ago.
Here's a quick example:
<p .innerHTML=${'<button onclick="alert(42)">click</button>'}></p>
This renders a button which produces an alert when you click on it. In this example the JavaScript code is harmless but it's not hard to imagine something way more dangerous.
However this simply renders the code as string. The content is somehow escaped and therefore totally harmless.
<p>${'<button onclick="alert(42)">click</button>'}></p>
In fact similar to React's dangerouslySetInnerHTML attribute you need to "opt out" from secure templating via lit-html unsafeHTML directive:
Renders the argument as HTML, rather than text.
Note, this is unsafe to use with any user-provided input that hasn't been
sanitized or escaped, as it may lead to cross-site-scripting vulnerabilities.
<p>${unsafeHTML('<button onclick="alert(42)">click</button>')}></p>
About DOMParser#parseFromString
In this introductory article about trusted-types we can see that this method is a known XSS sink.
Sure it won't execute <script> blocks but it won't sanitise the string for you. You are still at risk of XSS here:
<p .innerHTML="${(new DOMParser()).parseFromString('<button onclick="alert(42)">click</button>','text/html').body.innerHTML}"></p>

Handlebars inline onclick safe?

I have a handlebars template running client-side that renders variables inside an inline onclick like so:
<script id="my-handlebars-template" type="text/x-handlebars-template">
<button onclick="console.log('{{name}}');">Click Me!</button>
</script>
The context for this handlebars template is coming from an ajax call. name was user input on the sign in screen. My question is could someone launch an xss attack by changing their name to some malicious sequence of characters? For instance if name was );alert('hello would the handlebars template run the alert? From my testing, it does. This just seems wildly easy to write insecure code.
Here is a jsfiddle with a test. Notice how the alert is run when you click on the link );alert('hello.
http://jsfiddle.net/68tme0hr/1/
My question is could someone launch an xss attack by changing their name to some malicious sequence of characters?
Yes. Handlebars escaping only protects HTML.
If you're already in JS, then you are vulnerable.
There are two basic approaches for dealing with this.
Escape JavaScript data
Pass the data through JSON.stringify before putting it into the JS. The JS engine will then treat it as a literal.
Note that strings will get quotes added for you, do you don't need to do that
onclick="console.log({{name_after_json_stringify}});">
Put the data somewhere safer than in the middle of the JS
Such as in a data-* attribute
onclick="console.log(this.dataset.name);" data-name="{{name}}">
I recommend the second of these approaches as it is simpler and more readable.

Security of Angular expressions

I am going through the PhoneCat tutorial for AngularJS. Everything is explained really well, so i was following along until i hit step 6 in which links are generated dynamically from angular expressions:
http://localhost:8000/app/{{phone.imageUrl}}
While the tutorial states that ngSrc is preventing the browser from making http requests to invalid locations (edit: apparently the tutorial means the browser will only call the link after the expression got evaluated. See the "Experiments" section in the provided link.), i am now wondering of how secure angular-expressions are in general. Since the phone.imageUrl is loaded externally, it theoretically could contain malicious content and i would like to understand why this would not matter to my webapp.
Obviously the content of expressions gets escaped in some way, so including the following in your code will just print out some text:
<img ng-src="{{""><script>alert('UNSAFE!')</script>"}}">
but i would like to know if there are some "rules" that you need to be aware of to keep your webapp secure. Would for instance compiling the above code via
var template = "<img ng-src="{{""><script>alert('UNSAFE!')</script>"}}">";
var something = $compile(template);
result in executing the script when the DOM is loaded? Are there "things" that you should not do in your webapp when you can't ensure that the angular expressions contain the expected content?
As far as I know angular always escapes any data bound to elements unless you tell it not to do so.
Your example on the other hand works differently – maybe you're a little unsure how angular works:
var template = "<img ng-src="{{userInput}}">";
var something = $compile(template)({userInput: "\"><script>alert('UNSAFE!')</script>\""});
So the template, which you have full control of, get's first compiled and then the expression is bound to it completely escaped (no html allowed).
I'd probably not compile external code ($compile(userinput)) without sanitizing it first – but that would mean you may be doing something wrong. If you code the right way, you will use $compile only in some edge cases. Otherwise you may stay calm since angular will take care of unsafe input.
If you need to bind html to template, then you can include ngSanitize. Otherwise angular won't let you bind unsafe html, unless you tell the $sce service to trust it.
In conclusion, I would not worry about binding data from untrusted sources to my template.

Angular $sce vs HTML in external locale files

A question regarding ng-bind-html whilst upgrading an Angular app from 1.0.8 to 1.2.8:
I have locale strings stored in files named en_GB.json, fr_FR.json, etc. So far, I have allowed the use of HTML within the locale strings to allow the team writing the localized content to apply basic styling or adding inline anchor tags. This would result in the following example JSON:
{
"changesLater": "<strong>Don't forget</strong> that you can always make changes later."
"errorEmailExists": "That email address already exists, please sign in to continue."
}
When using these strings with ng-bind-html="myStr", I understand that I now need to use $sce.trustAsHtml(myStr). I could even write a filter as suggested in this StackOverflow answer which would result in using ng-bind-html="myStr | unsafe".
Questions:
By doing something like this, is my app now insecure? And if so, how might an attacker exploit this?
I can understand potential exploits if the source of the displayed HTML string was a user (ie. blog post-style comments that will be displayed to other users), but would my app really be at risk if I'm only displaying HTML from a JSON file hosted on the same domain?
Is there any other way I should be looking to achieve the marking-up of externally loaded content strings in an angular app?
You are not making your app any less secure. You were already inserting HTML in your page with the old method of ng-bind-html-unsafe. You are still doing the same thing, except now you have to explicitly trust the source of the HTML rather than just specifying that part of your template can output raw HTML. Requiring the use of $sce makes it harder to accidentally accept raw HTML from an untrusted source - in the old method where you only declared the trust in the template, bad input might make its way into your model in ways you didn't think of.
If the content comes from your domain, or a domain you control, then you're safe - at least as safe as you can be. If someone is somehow able to highjack the payload of a response from your own domain, then your security is already all manner of screwed. Note, however, you should definitely not ever call $sce.trustAsHtml on content that comes from a domain that isn't yours.
Apart from maintainability concerns, I don't see anything wrong with the way you're doing it. Having a ton of HTML live in a JSON file is maybe not ideal, but as long as the markup is reasonably semantic and not too dense, I think it's fine. If the markup becomes significantly more complex, I'd consider splitting it into separate angular template files or directives as needed, rather than trying to manage a bunch of markup wrapped in JSON strings.

How do I allow rails to have javascript: in the data

I have a database of ad html, and some of them contain Javascript functions. Is there a way to have rails allow javascript: tags for a particular attribute on a particular model?
To clarify further, I can bring the html up in an edit form, but when I try to submit, my browser (Firefox) says the connection is reset. IE gives me an error as well. The only thing that allows the html to be submitted is to remove the javascript: from the tag.
My guess is that this is a security measure by Rails to not allow javascript injection, however, I have no control over the html of these ads, and many have javascript in them.
If my guess is indeed correct, is there a way to override the security for this one attribute of this one model? Or am I way off target here?
I am using Rails 2.3.4 on Ruby 1.8.7
Now I've never used rails but the idea should be the same, you just want to store the javascript as a string, and then when you display it, do not escape the data. A better way to do this would be to link to your javascript and then just store calls to the functions in your database.
Without seeing any code, I'm guessing you are using sanitize. Instead of sanitizing, consider transmitting and storing your javascript escaped, then unescape it when you actually need to use it.

Categories

Resources