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.
Related
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>
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.
I'm looking at AngularJS, trying to learn the basics. Quite experienced with JavaScript and server programming, HTTP etc, so I do have an understanding of what it does. I'm watching Curran Keller's "50 examples" tutorial on YouTube (link below), and I've found lots of documentation on what Angular does... but not so much on how it does it. Knowing the rough on how Angular is able to do all these neat things -- it being "only" a JavaScript wrapper, executing in the web browser -- would be helpful when I am to write my first Angular "app" (webpage with metadata-enhanced JS, as I currently think of it). ;-) that ought to get the discussion going!
So, here's what I think I've gleaned so far:
Angular JS is JavaScript. It runs in the browser, via a .js file, so eventually the directives and tags and "angular code" (controller) is translated into JavaScript, which is what's actually run in the browser.
As such, Angular is really "just" a library of wrappers for normal JavaScript objects. I guess this is the main point; it's a simplification of the otherwise rather complex "native" JavaScript code. For example, rather than instantiating an XMLHttpRequest object, and using it to GET or POST some data to/from a server, Angular provides an $http service. All you need to type is $http.get();
Furthermore, Angular has this powerful dynamic propagation of changes in the UI, as the user uses the page. Almost like in Excel, if a piece of data is changed somewhere, then all other usages/references of same data (i.e. a variable, an HTML form element, or just a variable output to HTML with {{myVariable}}) are updated accordingly. Automatically, and immediately.
Another cool property is enhancing HTML tags with Angular directives. This is a very simple way of dynamically producing HTML output (or just plain text) from what ever is in the Angular (i.e. JavaScript) memory. Again, this can be done with plain vanilla JS, traversing the DOM and inserting child elements, but Angular alleviates the need for any of that complex coding. All you need to program is <li ng-repeat="name in names">{{name}}</li>
So, how does Angular achieve all this, using "only" JavaScript? Obviously, as with GetElementById, JavaScript can access (read) and parse the HTML DOM, so I take it Angular begins by reading in the entire document and looking for any HTML tags with the ng-app directive. These are parsed further, and Angular code is converted to either generate additional HTML output (e.g. ng-repeat), or translated into embedded JavaScript (as in $scope.name='';).
One thing I've had trouble finding an answer to in the documentation, is what the dollar signs do. I think I know the answer, but I'm not confident. Since Angular has its own JavaScript-like programming language, Angular needs to be able to discern between the JavaScript-parts (e.g. variables used in HTML FORM elements) and the Angular objects. I mean, what's Angular function calls and what's the input/arguments to those. Prepending $ to the Angular words lets the Angular JS-translator know what not to translate, so to speak?
Maybe someone can follow up on this, correct me where I'm wrong?
The examples in Curran Keller's "Introduction to Angular.js in 50 Examples" (http://youtu.be/TRrL5j3MIvo) is a great reference. For instance, maybe the dollowing simple example could be a starting point? In this example, I'm wondering (in addition to the above thoughts) what specifically is the purpose of the $scope object. Can we rename it to $whatever, or is "scope" a reserved word?
<html ng-app="nameApp">
<head>
<meta charset="utf-8">
<title>Angular.js Example 14</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.min.js"></script>
<script>
var nameApp = angular.module('nameApp', []);
nameApp.controller('NameCtrl', function ($scope) {
$scope.names = ['Larry', 'Curly', 'Moe'];
});
</script>
</head>
<body ng-controller="NameCtrl">
<ul>
<li ng-repeat="name in names">{{name}}</li>
</ul>
</body>
</html>
One thing I've had trouble finding an answer to in the documentation, is what the dollar signs do.
The dollar signs are simply a naming convention reserved for Angular and JQuery. It's simply for readability to quickly discern what is Angular/JQuery functions. See http://google.github.io/styleguide/angularjs-google-style.html#dollarsign.
In this example, I'm wondering (in addition to the above thoughts) what specifically is the purpose of the $scope object. Can we rename it to $whatever, or is "scope" a reserved word?
$scope is special, it refers to the application model. See docs.angularjs.org/guide/scope and docs.angularjs.org/guide/controller (can't post direct links because I don't have the reputation yet :( ).
In the above example, $scope is used to communicate between the controller and the DOM. The DOM can only refer to items on the scope in angular bindings. Breaking down the example above:
<body ng-controller="NameCtrl">
This instantiates the controller named NameCtrl, and sets up the same $scope between the DOM and that instance of NameCtrl. This element and all children elements can now reference the same $scope as NameCtrl.
$scope.names = ['Larry', 'Curly', 'Moe'];
This is where the controller is setting the model to Larry/Curly/Moe for the DOM to consume.
<li ng-repeat="name in names">{{name}}</li>
"names" refers to the same $scope.names in NameCtrl (remember, you don't write $scope from the DOM). Whenever the controller NameCtrl updates $scope.names, the DOM will update as well, creating a list item for each element in the array 'names', and each element has it's own $scope as well.
I suggest going through some of the AngularJS tutorial app helps quite a bit: docs.angularjs.org/tutorial/
I have been learning web application security penetration testing . The scenario is, there is a cross site scripting vulnerability in a test environment demo web application which is developed for practicing. I have a xss payload which is javascript expressions based :
<div style="width: expression(alert(/XSS/))"></div>
I know the expressions are deprecated since IE 8 .It works fine in IE7. So , when i input above payload , Web app returns with
<div></div>
It rips off all other attributes and values. But when i alter the payload like
<div style="width: expression'(alert(/XSS/))'">
Its not a valid payload means it won't execute. So, i am trying to figure out if there is any alternative to define expression in in-line style attribute like if we can place something else other than single_quote which won't break the code . Or if there is any other way to execute javascript via style attribute.
expression() is the only way to dynamically specify html node attributes. It takes any valid JScript expression as an argument. So technically there is no way to execute javascript via style attribute on an html node (JScript !== javascript).
The reason this functionality doesn't exist, (or has been deprecated) is because it creates a pretty big security vulnerability. If you want to have dynamic html elements, you'd tackle that with css, specifically through media queries. But if you want to go down this path, try checking out the expression() documentation.
In javascript (JScript as well), () invoke a function. So throwing ' or " after an expression name, before invoking it, is invalid syntax. There's probably something else you can place besides "single_quote" which won't break the code, but you wouldn't place it before the (). Try looking up JScript syntax. Here's one last resource that may help.
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.