Handlebars inline onclick safe? - javascript

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.

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 JS is processing HTML as String [duplicate]

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.

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.

Struts tags in Javascript

What would you consider a better practice?
Would you do (in javascript):
var aaa = <s:property value="myValue"/>;
or rather (in a jsp file):
<s:hidden name="myValue" id="myValue" />
with (in javascript):
var bbb = document.getElementById("myValue").value;
Well that depends I think. You can't use struts2 tags in JS files unless you save them as .jsp. In case you do this or you have a JS code in your page, I personally doesn't have a problem with the first option, since the tags will be processed back at server. I use this often when there is a simple assignment.
I don't like the second option cause it makes the code a little ugly and might cause some maintenance problems.
To sum it up it's a better practice to separate your JS and server side codes. If you find yourself mixing things up you might want to look at your design somewhere that could change.
Again that depends on how you prefer to do it.
You can achieve the desired results with both way.only thing matters is individual taste and preferences.
i would not like to mix up the things and will go with the second way using a hidden field.for me it serve 2 purposes.
separating my struts2 tag from the JavaScript.
More over i can write a simple clean JavaScript code with standard JavaScript method rather mixing up the things
There are many ways, including what you've shown.
You may also:
Pass JavaScript files through the JSP processor
Use a different templating language for dynamic JS (like FreeMarker)
Emit a JSON object evaluated before your JS files are included (e.g., the contents of a hidden div are evaluated purely for JS side-effects)
Make an Ajax call for the same JSON object on page load before your functionality fires
Probably a few more. I don't prefer hidden fields unless they're in a form that isn't submitted (like a hidden, separate form) unless it's very clear which form values matter and which don't.

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