You’re not likely to find a web application that doesn’t use a sophisticated front-end framework like Angular. One of the selling points of front-end frameworks like Angular has been their best effort to prevent Cross-site Scripting (XSS) by escaping characters that could be interpreted as code. These efforts are commendable since XSS has been a major problem in web applications for quite some time.
As frameworks like Angular get older, they inevitably grow by adding new functionality. This functionality also increases complexity, and with complexity, new vulnerabilities creep in. Even though Angular tries to do some things to help prevent XSS vulnerabilities, there are still holes attackers can exploit to get their code to execute within your application.
Let’s look at three such flaws that developers could overlook and could be used to cause XSS attacks.
Loading angular templates insecurely
Angular templates can be loaded into a view using the TemplateURL property. By default, Angular only allows templates to be loaded by the same domain and protocol as the application document. However, this can be circumvented. If you need to load templates from another domain, you can create a custom whitelist of domains from which templates can be loaded.
The whitelist can be made to be too permissive. The wrong configuration will tell Angular to load templates from any domain and using any protocols. Loading templates that could be under an attacker’s control is an easy path to compromise.
The whitelist can be created with the $sceDelegateProvider.resourceUrlWhitelist function.
1
2
3
4
5
6
7
8
9
|
angular.module( 'yourAppHere' , []).config( function ($sceDelegateProvider) { $sceDelegateProvider.resourceUrlWhitelist([ ** // This wildcard whitelists all domains and all protocols ]); } |
If you have to use a whitelist, make sure you only whitelist domains you trust and never use the wildcard. Also specify the HTTPS protocol to make sure the domain certificate is valid when you pull the template down. These simple measures will keep your templates free from malicious code.
Expression injection
Angular gives developers the ability to dynamically create content within HTML pages using templates. Templates allow a developer to define placeholders within the text of an HTML page that are evaluated at runtime by Angular. For example, when you place the expression “2 * 2” into a template, the rendered page will place a “4” into the page (the value of the expression).
Those of you that are familiar with security concepts may already know where this is going. If your attacker can control what is placed into these expression placeholders, they can execute arbitrary code. This happens when the values entered into an input box are dynamically added into the page.
Generating templates dynamically on the server-side is a dangerous way to create HTML pages and opens up your application to many vulnerabilities. If your server places user input back into the templates without proper escaping and sanitization, you’ll have an injection vulnerability. And Angular doesn’t do everything for you in this respect. It will only escape HTML symbols, opening the door for JavaScript expressions or CSS expressions to still be returned to the browser and executed as code.
The best way to generate templates while greatly reducing the risk of injection attacks is to use the Angular Ahead-of-Time (AOT) Compiler. The AOT compiler compiles templates at build time instead of using a just-in-time compilation at run-time. The JavaScript your application uses is created before the users have a chance to see it or manipulate it. It also has the side benefit of reducing your application’s footprint and increasing performance.
If you don’t want to use AOT compilation, then sanitization will help you. Remove any double braces [ {{ ] in user input fields before adding it to the templates. Angular trusts template expressions implicitly, so you have to make sure only trusted and thoroughly checked data gets added to templates.
Trusting the AngularJS sandbox
You may be thinking, “Doesn’t Angular execute in a sandbox? That means any code entered won’t touch my actual computer and I’m protected.” Unfortunately, that simply is not the case. The sandbox for AngularJS has been shown to be vulnerable to breakouts time and time again. In fact, there have been entire posts outlining several ways to break out of AngularJS sandboxes.
The point here is short and simple. Don’t relax your security precautions because you trust that Angular’s sandbox will protect you. Always assume that an attacker knows how to escape the sandbox and instead focus on preventing his code from executing in the first place.
Automatic escaping doesn’t mean absolute protection
Angular, and other front-end frameworks, have made important strides toward protecting against XSS attacks. But it’s important to understand exactly how the measures work and what their limitations are. You can’t assume that the framework steps in no matter what and prevents all malicious code execution.
Defend your Angular apps from XSS by only loading templates from trusted sources. Don’t dynamically generate templates with user-controlled data, compile them ahead of time instead. And never trust that the sandbox is enough to prevent exploitation if you aren’t careful.
Keep these tips in mind and you’ll be able to escape a malicious attack against your application.