Mastodon

Introducing AngularJS Security Fundamentals on Pluralsight

If I’m honest, I always found it a bit unusual to get this question:

“How do I secure my Angular apps?”

I mean, Angular is just JavaScript that runs in the client and a few HTML directives. Ok, it’s very good JavaScript and I don’t mean to trivialise the framework in any way whatsoever, but all the security grunt work still needs to happen on the server. Angular will do nothing for your SQL injection or your lack of access controls on server resources or any of the other really nasty security stuff that tends to go wrong in web apps. Yet the question kept coming up and the more I thought about it, the more it made it sense to put Angular security in perspective. So I made this Pluralsight course:

Angular JS Security Fundamentals

The very fact alone that developers kept asking about Angular security was enough motivation to do a course on it. Let me explain how I’ve approached it.

Start by getting your head around it

I often wonder if the Angular security question comes from those who are perhaps newer to web development and whose world centres more around Angular as a product rather than where it fits into the broader web app ecosystem. For example, how well attuned are developers to the fact that it’s easy just to take Angular out of the picture altogether and issue requests directly to the API on the server? Some people might scoff at the assertion that this isn’t broadly understood, but trust me, it’s commonly missed. In fact that’s one of the things I focus on in my Hack Your API first course and it’s a particularly prevalent mindset in the world of mobile apps.

One of the first things I do in the course is very clearly segment client from network from server. Clearly Angular is a purely client side technology so it lives in the world of the DOM, has to deal with things like cross site scripting and benefits from defences such as secure and HTTP only cookies. It’s not going to help you secure you network or server stacks and I spend a bit of time outlining the discrete risks and defences there in terms of how they need to be tackled independently of the client.

This is one of the things that people often overlook in the design of their app, be they Angular other:

Graphic on what you can control (only the server)

It’s a trust assumption issue – “I built this JavaScript and it will always run the way I intended it to” – and it’s a dangerous assumption. As I mentioned earlier, you can always substitute the client for something else (even just CURL) and you can always tamper with traffic on the wire, even if it’s sent over HTTPS and you own the client. The server is where the real resiliency needs to be and one of the key points I make very early on is simply this: always assume the client is compromised!

This helps with how to think about Angular, next up is how to start breaking bits of apps built with it.

Working with security controls on the server

A lot of this comes down to how apps are authenticating and then authorising requests to server resources. Some of this is the same as with web apps built in the more “traditional” way where a wall of HTML posts back to the server, unloads from the DOM and then grabs an entirely new wall of HTML. But a lot of it also differs when you move to lightweight asynchronous requests designed to merely manipulate the DOM.

Identity persistence, for example, suddenly takes on a whole new shape or at least it can do. Normally we’d throw an auth cookie into the browser on login and all subsequent requests would be auth’d by virtue of that cookie implicitly being sent. But cookies aren’t “RESTful” (you can read some of my views on RESTfulnes here) and the view of API requests is that they generally should be sent via bearer tokens instead. Now that’s not hard to do and it has a number of advantages over cookies anyway (CSRF defence, for example), but you still have to persist it on DOM unload. Some people put it in a cookie and then orchestrate it’s retrieval via JavaScript so that it can be appended to API requests, but now the cookie can’t be flagged as HTTP only so it’s vulnerable to any XSS risks. There are other ways, but this gives a sense of the sort of issues I tackle in the course.

One thing worth pointing out here is that I don’t go into “This is exactly how to implement this end to end in Angular and [insert favourite server side framework here]”. It’s a server platform agnostic course, that is it’s equally relent to ASP.NET as it is PHP or Node or whatever your favourite flavour of stuff that executes on the server is. This is the same approach I’ve taken with other courses such as Hack Yourself First and Secure Account Management Fundamentals and I’ve found that breadth rather than depth works well for this style of course. What I do focus on though is the behaviours the app should demonstrate so I go through both anti-patterns and good practices, explaining their respective pitfalls and merits. There’s also a sample app that’s used in the course and is public for people to play with over at awesomeplaces.troyhunt.com and incidentally, that’s built on ASP.NET using MVC and Web API.

There’s a bunch of other stuff in the module on server security controls, but it’s the next module that I suspect will unsettle more than a few Angular devs out there…

Common security flaws on the client side

Let us begin by basking in the warm glow of this brilliance:

HTML comments disclosing admin account password

You know what’s wrong with this. I know what’s wrong with this. Heck, even the dev that wrote it probably knows what’s wrong with it, yet here it is in all its glory. Clearly this isn’t Angular, but it illustrates a very important point – anything sent to the client is observable by those who receive it! I know, who’d have thunk it, but it’s an important point in Angular because it does a lot of work the server normally would in a more traditional app. All that model binding and orchestration of service calls and loading of templates is now on public display. When you send a controller down to the client in a script file and it contains references to that “hidden” admin factory which then calls into a service to manage your users, that’s now public info.

Should you send that info to the client pre-auth? That’s one of the things I discuss in the course and naturally I emphatically talk about protecting the services that are “hidden” by the client. Showing the right things to the right people and trusting the browser to make those decisions for you is wonderful in an AJAX’y, responsive sort of way, but none of that negates the earlier point – you do not control the client.

Naturally I also look at other attacks that happen in the browser so things like the risk of XSS and how Angular handles output encoding (it’s actually rather clever), the role of cookies and those secure and HTTP only attributes and then a bit on CSRF as well. As it turns out, Angular has quite a neat way of helping you get your anti forgery tokens in check and that’s something I cover in the next module…

Security constructs within AngularJS

In the course, I point out that the Angular security documentation is, well, a little sparse:

The Angular security documentation page

That’s it. That’s the entire page. There’s a link off to ngCsp but that’s it. Now you can see why that question about how to secure Angular keeps coming up!

But there actually some very neat security constructs in Angular. For example, I mentioned some CSRF magic earlier on: if you have a cookie called “XSRF-TOKEN” then Angular will automatically convert it to a custom request header called “X-XSRF-TOKEN” and send it with any request invoked via the $http service where your favourite server framework can then validate the token and do it’s anti-forgery magic.

Another neat trick is the ngSanitize module (everyone outside America, do note the spelling, not much happens otherwise!). This changes Angular’s approach to output encoding and implements a whitelist of allowable HTML tokens whilst stripping everything else out. Now frankly, sanitisation is always a bit of a quagmire but Angular does do quite a nice implementation of it.

Then there’s the full “you’re now on your own” with regards to output encoding which is to totally turn off strict contextual escaping and just trust that all the data you plug into that context is safe. It’s the “it’s your own foot” approach and I show how as good as Angular is, you can still screw it up pretty badly.

Speaking of which, guess what happens when you put untrusted data from user input into a template rendered on the server side? Let’s just say it’s not pleasant and I demonstrate why this is one of the few pieces of guidance Google actually put on that Angular security page above.

My approach to this module and indeed this entire course – as it is with my others – is this: show people how to break their things. Let them understand what can go wrong and experience it firsthand because unless they’re really engaged in the risks associated with these patterns, it’s very hard for them to buy into the effort that’s required to defend their apps.

It’s an Angular course that isn’t about Angular

Originally, I’d not intended to make this an Angular course. Instead, I was going to make it a more generic course that applied equally to Angular as it does to, say, Backbone or Ember. My thinking was that the implementation of the client side library wasn’t really the point, rather it was more about understanding where the risks lie in an app that moves a lot of the logic into the browser. That’s still my view of things and to that effect, the first four modules of the course are relevant regardless of your favourite Thing.JS framework. But clearly Angular has got enormous momentum at the moment and it simply ended up being a more broadly relevant way of describing the course.

That said, the final module described above is all about Angular. It looks specifically at what we’ve got access to in the framework and how to use and misuse it. I hope this gives the course the broadest possible relevance.

Because security slip ups are everywhere

As I started recording the course, I loaded up the Angular website and…

The Angular website with mixed content

Mixed content. Bugger. This is Google’s web browser loading the website for Google’s framework and showing Google’s warning that parts of the page are insecure. They pretty much own the end-to-end stack here but still, this has slipped in. It’s not a major security risk, but warning symbols tend to be the sort of thing you don’t want on your product website!

This is almost certainly an oversight and it goes to illustrate much of what I talk about in the course, namely that it’s easy it get this stuff wrong. One little XSS risk, for example, combined with one cookie accessible by client script (which is somewhat common in Angular apps) and there you go – sessions hijacked!

In closing…

This course should get anyone building Angular thinking about where the framework fits into the broader security landscape in a way that’ll help them understand the risks. It puts Angular – and other JS frameworks – into perspective and makes it very clear what it is and what it is not when it comes to security. Angular is many wonderful things, but it provides a mere small piece of the security picture in an Angular website.

Finally, for those unfamiliar with Pluralsight, it’s a subscription model service with costs kicking off at $29/m and giving you access to near on 4,000 courses on a heap of development topics and a bunch of IT pro and creative ones as well. As an author, I receive a royalty based on how much my content is watched and I can only do what it is that I do because my courses get eyeballs on them. So if you’re into Angular or security in general, check out my Pluralsight courses and help me keep the content coming!

Pluralsight Security
Tweet Post Update Email RSS

Hi, I'm Troy Hunt, I write this blog, create courses for Pluralsight and am a Microsoft Regional Director and MVP who travels the world speaking at events and training technology professionals